package com.zmn.oms.zmn.business.impl.work.customwork;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerBasicInfoDRO;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.common.enums.EngineerOAStatusEnum;
import com.zmn.base.engineer.common.enums.EngineerStopOrderStatusEnum;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWorkMaster;
import com.zmn.base.product.common.dto.categ.ClassifyDRO;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.base.sdss.common.model.dio.oms.EngineerProductGroupCompositeScoreForDispatchOrderDIO;
import com.zmn.base.sdss.common.model.dro.oms.EngineerProductGroupCompositeScoreForDispatchOrderDRO;
import com.zmn.base.sdss.dubbo.interfaces.oms.CompositeServeScoreForOmsListRemoteService;
import com.zmn.biz.engineer.common.dro.area.EngineerServScopeStatusDRO;
import com.zmn.biz.engineer.common.dro.distribute.EngineerDistributeOrderDRO;
import com.zmn.biz.engineer.common.dro.distribute.EngineerSupportDistributeOrderDRO;
import com.zmn.biz.engineer.common.dro.schedule.WorkingTimeDRO;
import com.zmn.biz.engineer.common.enums.NotSupportDistributeOrderEnum;
import com.zmn.biz.engineer.common.query.area.EngineerServScopeStatusQuery;
import com.zmn.biz.engineer.common.query.distribute.*;
import com.zmn.biz.engineer.dubbo.interfaces.area.EngineerServAreaListRemoteService;
import com.zmn.biz.engineer.dubbo.interfaces.distribute.DistributeOrderAssistListRemoteService;
import com.zmn.biz.engineer.dubbo.interfaces.distribute.PlatDistributeOrderListRemoteService;
import com.zmn.biz.engineer.dubbo.interfaces.distribute.SPDistributeOrderListRemoteService;
import com.zmn.biz.engineer.dubbo.interfaces.schedule.ScheduleListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.map.Point;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.gms.common.dio.grid.online.engineer.DistanceGridEngInfoQuery;
import com.zmn.gms.common.dio.grid.online.engineer.EngineerAdjoinGridDIO;
import com.zmn.gms.common.dio.grid.online.engineer.EngineerInCoordGridTypeDIO;
import com.zmn.gms.common.dio.grid.online.grid.CircleRangeDIO;
import com.zmn.gms.common.dto.online.engineer.EngineerAdjoinGridDRO;
import com.zmn.gms.common.dto.online.engineer.EngineerGridTypeDRO;
import com.zmn.gms.common.dto.online.grid.GridBaseDRO;
import com.zmn.gms.dubbo.interfaces.grid.online.engineer.GridEngineerListRemoteService;
import com.zmn.gms.dubbo.interfaces.grid.online.grid.GridListRemoteService;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.apply.CancelApplyBService;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.business.interfaces.conf.distribute.DistributeWeightListBService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.business.interfaces.tmall.OrderTmallExtendBService;
import com.zmn.oms.business.interfaces.worktrack.WorkTrackBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.redistribute.EngineerRedistributeQuery;
import com.zmn.oms.common.dro.conf.channel.ConfOrderChannelDRO;
import com.zmn.oms.common.dro.conf.distribute.DistributeArgsDRO;
import com.zmn.oms.common.dro.conf.distribute.DistributeConfigDRO;
import com.zmn.oms.common.dro.conf.distribute.DistributeEngineerLevelGroupDRO;
import com.zmn.oms.common.dro.conf.distribute.PlatDirectlyDistributeArgsDRO;
import com.zmn.oms.common.enums.MasterStockTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.manager.utils.MongodbConsts;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.bo.distribute.ReworkOriginalEngineerBO;
import com.zmn.oms.model.bo.stock.DistributeMasterStockBO;
import com.zmn.oms.model.bo.work.apply.cancel.CancelApplyResultBO;
import com.zmn.oms.model.dto.work.distribute.MqWaitDistributeDTO;
import com.zmn.oms.model.dto.work.modify.OrderDistributeDTO;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.conf.distribute.DistributeWeightQuery;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.tamllextend.OrderTmallExtend;
import com.zmn.oms.model.entity.work.DistributeMasterQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.mongo.distribute.PlaceAnOrderPreDistribute;
import com.zmn.oms.model.mongo.distributesnapshot.DistributeSnapshot;
import com.zmn.oms.model.vo.work.*;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.aop.OrderWorkLogUtils;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsCustomWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import com.zmn.performance.common.dio.MasterOverviewDIO;
import com.zmn.performance.common.dio.master.EngineerInfoDIO;
import com.zmn.performance.common.dio.master.MasterOverviewHistoryDIO;
import com.zmn.performance.common.dro.distribute.metrics.DistributeMetricsDRO;
import com.zmn.performance.common.dro.master.MasterOverviewHistoryDRO;
import com.zmn.performance.common.dro.master.MasterOverviewIntegrateDRO;
import com.zmn.performance.dubbo.interfaces.distribute.metrics.DistributeMetricsListRemoteService;
import com.zmn.performance.dubbo.interfaces.master.MasterOverviewListRemoteService;
import com.zmn.track.common.constant.TrackConsts;
import com.zmn.track.dubbo.dto.TrackWorkQuery;
import com.zmn.track.dubbo.interfaces.trackwork.TrackWorkListRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 类描述：派单
 *
 * @author liuying
 * @date 2018/11/02 21:02
 */
@Service
public class ZsDistributeWorkBServiceImpl implements ZsDistributeWorkBService {

    // 是否使用导航距离
    protected static final boolean useNavigationDistance = true;

    private static final double MAX_DISTANCE = 9999999999D;

    // 后台服务分类
    private static final String CATEG = "categ";

    // 派单快照时间格式
    private static final String FORMAT_DATETIME4 = "yyMMddHHmmss";

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected OrderWorkService orderWorkService;

    @Autowired
    protected OrderDetailService orderDetailService;

    @Autowired
    protected OrderTmallExtendBService orderTmallExtendBService;

    @Autowired
    private OrderWorkEsBService orderWorkEsBService;

    @Autowired
    private ZsCustomWorkBService zsCustomWorkBService;

    @Autowired
    private ConfOrderChannelBService confOrderChannelBService;

    @Autowired
    private OrderLogBService orderLogBService;

    @Autowired
    private OrderStockBService orderStockBService;

    @Autowired
    private WorkTrackBService workTrackBService;

    @Autowired
    OrderChangeRecordService orderChangeRecordService;

    @Resource
    private BaiduMapBService baiduMapBService;

    @Resource
    private DistributeWeightListBService distributeWeightListBService;

    @Resource
    private ZmnMQSender zmnMQSender;

    @Resource
    private RedisManager redisManager;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private OrderTagService orderTagService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private CancelApplyBService cancelApplyBService;
    @Resource
    private OrderEncryptService orderEncryptService;

    @DubboReference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerServAreaListRemoteService engineerServAreaListRemoteService;
    @DubboReference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private DistributeOrderAssistListRemoteService distributeOrderAssistListRemoteService;

    @DubboReference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private SPDistributeOrderListRemoteService spDistributeOrderListRemoteService;

    @DubboReference(version = com.zmn.performance.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private MasterOverviewListRemoteService masterOverviewListRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;

    @DubboReference(version = com.zmn.performance.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private DistributeMetricsListRemoteService distributeMetricsListRemoteService;

    @DubboReference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private TrackWorkListRemoteService trackWorkListRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private PlatDistributeOrderListRemoteService platDistributeOrderListRemoteService;


    @DubboReference(version = com.zmn.gms.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private GridListRemoteService gridListRemoteService;

    @DubboReference(version = com.zmn.gms.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private GridEngineerListRemoteService gridEngineerListRemoteService;

    @DubboReference(version = com.zmn.base.sdss.dubbo.interfaces.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private CompositeServeScoreForOmsListRemoteService compositeServeScoreForOmsListRemoteService;

    @DubboReference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private ScheduleListRemoteService scheduleListRemoteService;

    @NacosValue(value = "${grid.bind.city:}", autoRefreshed = true)
    private String gridBindCity;

    /**
     * 根据两点间经纬度坐标（double值），计算两点间拐角距离，单位为米
     *
     * @param lng1
     * @param lat1
     * @param lng2
     * @param lat2
     * @return
     */
    private static double getCornerDistance(double lng1, double lat1, double lng2, double lat2) {
        double s = 0.0;

        do {
            // 位置相同
            if (lng1 == lng2 && lat1 == lat2) {
                break;
            }

            // 经度或者纬度之一相同
            if (lng1 == lng2 || lat1 == lat2) {
                s = MathUtil.GetDistance(lng1, lat1, lng2, lat2);
                break;
            }

            // 经度和纬度都不同，转换为两个拐弯距离之和
            double s1 = MathUtil.GetDistance(lng1, lat1, lng1, lat2);
            double s2 = MathUtil.GetDistance(lng1, lat1, lng2, lat1);

            s = s1 + s2;
        } while (false);

        return s;
    }


    /**
     * 获取派单缘由
     *
     * @param orderId
     * @param workId
     * @param masterId
     * @return
     */
    @Override
    public DistributeReasonVO checkDistributeReason(Long orderId, Long workId, Integer masterId, boolean isGridDistribute) {

        // 返回的结果VO
        DistributeReasonVO distributeReasonVO = new DistributeReasonVO();
        distributeReasonVO.setStatus(GlobalConsts.YES);
        distributeReasonVO.setReason("该工程师符合派单");

        // 查询订单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderId);

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, isGridDistribute);
        distributeMasterQuery.setMasterId(masterId);

        // 返修原单工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        distributeMasterQuery.setOriginalMasterId(reworkMasterId);

        do {

            // 获取派单参数
            DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
            if (distributeConfigDRO == null) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason("获取派单参数失败");
                break;
            }

            DistributeArgsDRO distributeArgsDRO;

            // PS:网格化差异点
            if (isGridDistribute) {
                distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
            }
            else {
                distributeArgsDRO = distributeConfigDRO.getDistributeArgsDRO();
            }

            // 是否开启简单派单
            boolean simpleStatus = false;
            // 是否开启推荐派单
            boolean recommendStatus = false;
            // 是否开启公平派单
            boolean fairStatus = false;

            // 简单派单
            if (Objects.equals(distributeArgsDRO.getNewSimpleStatus(), GlobalConsts.YES)) {
                simpleStatus = true;
            }

            // 推荐派单
            if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND)) {
                recommendStatus = true;
            }
            // 公平派单
            else if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR)) {
                fairStatus = true;
            }

            // 调用工程师服务检查基本条件

            EngineerSupportDistributeOrderQuery cannotDistributeOrderReasonQuery = new EngineerSupportDistributeOrderQuery();

            cannotDistributeOrderReasonQuery.setSerialNumber(UUID.randomUUID().toString());

            cannotDistributeOrderReasonQuery.setEngineerId(distributeMasterQuery.getMasterId());
            cannotDistributeOrderReasonQuery.setOriginalEngineerId(distributeMasterQuery.getOriginalMasterId());
            cannotDistributeOrderReasonQuery.setPlat(distributeMasterQuery.getPlat());
            cannotDistributeOrderReasonQuery.setBizType(distributeMasterQuery.getBizType());
            cannotDistributeOrderReasonQuery.setChannelId(distributeMasterQuery.getChannelId());
            cannotDistributeOrderReasonQuery.setSubCompanyId(distributeMasterQuery.getCompanyId());
            cannotDistributeOrderReasonQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
            cannotDistributeOrderReasonQuery.setCityId(distributeMasterQuery.getCityId());
            cannotDistributeOrderReasonQuery.setOrderLat(distributeMasterQuery.getLatitude());
            cannotDistributeOrderReasonQuery.setOrderLng(distributeMasterQuery.getLongitude());
            cannotDistributeOrderReasonQuery.setDutyTime(distributeMasterQuery.getDutyTime());
            // PS:网格化差异点
            cannotDistributeOrderReasonQuery.setGridScreen(isGridDistribute ? GlobalConsts.YES : GlobalConsts.NO);

            // 后台技能
            List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                    distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
            cannotDistributeOrderReasonQuery.setServSkillList(servSkillLists);

            // 后门开关永远开
            Integer backDoorStatus = GlobalConsts.YES;
            cannotDistributeOrderReasonQuery.setSkipServAreaCheck(backDoorStatus);
            cannotDistributeOrderReasonQuery.setSkipOnlineCheck(backDoorStatus);
            cannotDistributeOrderReasonQuery.setMaxProbationCycle(7);
            logger.info("检查师傅不能被派单原因入参:[{}]", JSON.toJSONString(cannotDistributeOrderReasonQuery));
            ResponseDTO<EngineerSupportDistributeOrderDRO> responseDTO = distributeOrderAssistListRemoteService.checkEngineerSupportDistributeOrder(cannotDistributeOrderReasonQuery);
            logger.info("检查师傅不能被派单原因出参:[{}]", JSON.toJSONString(responseDTO));
            if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason("工程师信息错误");
                //logger.info("工程师信息错误");
                break;
            }

            EngineerSupportDistributeOrderDRO cannotDistributeOrderReasonDRO = responseDTO.getData();

            StringJoiner sj = new StringJoiner("；");

            // 基本条件检查没通过，返回接口定义的提示信息
            if (Objects.equals(cannotDistributeOrderReasonDRO.getDistributeOrderStatus(), GlobalConsts.NO)) {
                //distributeReasonVO.setStatus(GlobalConsts.NO);
                cannotDistributeOrderReasonDRO.getNotDistributeOrderList().forEach(e -> {
                    sj.add(e.getName());
                });
                //distributeReasonVO.setReason(cannotDistributeOrderReasonDRO.getNotDistributeOrderEnum().getName());
                //logger.info("基本条件检查没通过，返回接口定义的提示信息");
                //break;
            }

            // 如果是返修单并且是原工程师，不检查了
            if (Objects.equals(distributeMasterQuery.getOrderType(), OrderConsts.ORDER_TYPE_REWORK)
                    && distributeMasterQuery.getMasterId() != null && distributeMasterQuery.getMasterId() > 0
                    && Objects.equals(distributeMasterQuery.getMasterId(), distributeMasterQuery.getOriginalMasterId())) {
                //logger.info("如果是返修单并且是原工程师，不检查了");
                if (sj.length() > 0) {
                    distributeReasonVO.setStatus(GlobalConsts.NO);
                    distributeReasonVO.setReason(sj.toString());
                }
                break;
            }

            // 不是C端订单，就不走下面的检查逻辑了
//            if (!Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
//                break;
//            }

            // 最大手头返修单：默认0
            int maxReworkCount = 0;

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            // 最大返修催单量：默认0
            int maxReworkReminderCount = 0;
            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }

            /*
            // 最大手头返修单没有设置，下面的检测逻辑就不走了
            if (maxReworkCount <= 0) {
                break;
            }
            */

            // 只查询当前工程师
            DistributeMasterQuery curDistributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, isGridDistribute);
            curDistributeMasterQuery.setMatchMasterIdList(Lists.newArrayList(masterId));
            curDistributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

            List<ZsOrderDistributeVO> masterList = this.listForUnrestrictedDistributeOrder(curDistributeMasterQuery);
            // PS:网格化差异点
            /*if (isGridDistribute) {
                masterList = this.listGridDistributeMasterByQuery(curDistributeMasterQuery);
            }
            else {
                masterList = this.listSpDistributeMasterByQuery(curDistributeMasterQuery);
            }*/

            // 查询失败
            if (CollectionUtils.isEmpty(masterList)) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                sj.add("没有查询到指定的工程师信息");
                distributeReasonVO.setReason(sj.toString());
                //logger.info("没有查询到指定的工程师信息");
                break;
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            if (isGridDistribute) {
                // PS:网格化差异点，获取工程师列表网格信息
                this.getMasterListGridInfo(masterList, distributeMasterQuery);
            }

            // 检查基础条件
            Integer supportGridCountLimit = null;
            if (isGridDistribute) {
                supportGridCountLimit = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getSupportGridCountLimit();
            }

            this.checkBaseDistributeReason(masterList.get(0), distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj);
            /*if (StringUtil.isNotBlank(reason)) {
                sj.add(reason);
                //break;
            }*/

            // 如果是返修单或者开启新单简单派单，结束
            if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || simpleStatus) {
                if (sj.length() > 0) {
                    distributeReasonVO.setStatus(GlobalConsts.NO);
                    distributeReasonVO.setReason(sj.toString());
                }
                //logger.info("如果是返修单或者开启新单简单派单，结束");
                break;
            }

            // 调用工程师服务查询app位置在线和服务范围状态
            this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

            // 服务商派单，非直营工程师检查是否在线
            if (isGridDistribute) {
                masterList = this.onlineStatusFilter(masterList);
                if (CollectionUtils.isEmpty(masterList)) {
                    distributeReasonVO.setStatus(GlobalConsts.NO);
                    sj.add("非直营工程师App不在线");
                    distributeReasonVO.setReason(sj.toString());
                    //logger.info("非直营工程师App不在线");
                    break;
                }
            }

            // 查询师傅统计信息并计算评分
            this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

            List<ZsOrderDistributeVO> inScopeMasterList = masterList;

            // PS:网格化差异点
            if (!isGridDistribute) {

                // 判断服务范围
                inScopeMasterList = this.scopeStatusFilter(masterList);

                if (CollectionUtils.isEmpty(inScopeMasterList)) {
                    distributeReasonVO.setStatus(GlobalConsts.NO);
                    sj.add("不在服务范围");
                    distributeReasonVO.setReason(sj.toString());
                    //logger.info("不在服务范围");
                    break;
                }
            }

            // 检查推荐派单
            if (recommendStatus || fairStatus) {
                //logger.info("检查推荐派单");
                this.checkRecommendDistributeReason(inScopeMasterList, distributeMasterQuery, sj);
                /*if (StringUtil.isNotBlank(reason)) {
                    sj.add(reason);
                }*/
                //break;
            }

            if (sj.length() > 0) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason(sj.toString());
            }

        } while (false);

        return distributeReasonVO;
    }

    @Override
    public DistributeReasonVO checkDistributeReason(DistributeMasterQuery distributeMasterQuery, DistributeConfigDRO distributeConfigDRO, boolean isGridDistribute) {
        DistributeReasonVO distributeReasonVO = new DistributeReasonVO();

        distributeReasonVO.setStatus(GlobalConsts.YES);
        distributeReasonVO.setReason("该工程师符合派单");

        if (distributeConfigDRO == null) {
            distributeReasonVO.setStatus(GlobalConsts.NO);
            distributeReasonVO.setReason("获取派单参数失败");
            return distributeReasonVO ;
        }

        this.getDistributeReason(distributeReasonVO, distributeMasterQuery, distributeConfigDRO, isGridDistribute);
        return distributeReasonVO;
    }


    private void getDistributeReason(DistributeReasonVO distributeReasonVO, DistributeMasterQuery distributeMasterQuery, DistributeConfigDRO distributeConfigDRO, boolean isGridDistribute) {
        DistributeArgsDRO distributeArgsDRO;

        // PS:网格化差异点
        if (isGridDistribute) {
            distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
        }
        else {
            distributeArgsDRO = distributeConfigDRO.getDistributeArgsDRO();
        }

        // 是否开启简单派单
        boolean simpleStatus = false;
        // 是否开启推荐派单
        boolean recommendStatus = false;
        // 是否开启公平派单
        boolean fairStatus = false;

        // 简单派单
        if (Objects.equals(distributeArgsDRO.getNewSimpleStatus(), GlobalConsts.YES)) {
            simpleStatus = true;
        }

        // 推荐派单
        if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND)) {
            recommendStatus = true;
        }
        // 公平派单
        else if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR)) {
            fairStatus = true;
        }

        // 调用工程师服务检查基本条件

        EngineerSupportDistributeOrderQuery cannotDistributeOrderReasonQuery = new EngineerSupportDistributeOrderQuery();

        cannotDistributeOrderReasonQuery.setSerialNumber(UUID.randomUUID().toString());

        cannotDistributeOrderReasonQuery.setEngineerId(distributeMasterQuery.getMasterId());
        cannotDistributeOrderReasonQuery.setOriginalEngineerId(distributeMasterQuery.getOriginalMasterId());
        cannotDistributeOrderReasonQuery.setPlat(distributeMasterQuery.getPlat());
        cannotDistributeOrderReasonQuery.setBizType(distributeMasterQuery.getBizType());
        cannotDistributeOrderReasonQuery.setChannelId(distributeMasterQuery.getChannelId());
        cannotDistributeOrderReasonQuery.setSubCompanyId(distributeMasterQuery.getCompanyId());
        cannotDistributeOrderReasonQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
        cannotDistributeOrderReasonQuery.setCityId(distributeMasterQuery.getCityId());
        cannotDistributeOrderReasonQuery.setOrderLat(distributeMasterQuery.getLatitude());
        cannotDistributeOrderReasonQuery.setOrderLng(distributeMasterQuery.getLongitude());
        cannotDistributeOrderReasonQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        // PS:网格化差异点
        cannotDistributeOrderReasonQuery.setGridScreen(isGridDistribute ? GlobalConsts.YES : GlobalConsts.NO);

        // 后台技能
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
        cannotDistributeOrderReasonQuery.setServSkillList(servSkillLists);

        // 后门开关永远开
        Integer backDoorStatus = GlobalConsts.YES;
        cannotDistributeOrderReasonQuery.setSkipServAreaCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setSkipOnlineCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setMaxProbationCycle(7);
        logger.info("检查师傅不能被派单原因入参:[{}]", JSON.toJSONString(cannotDistributeOrderReasonQuery));
        ResponseDTO<EngineerSupportDistributeOrderDRO> responseDTO = distributeOrderAssistListRemoteService.checkEngineerSupportDistributeOrder(cannotDistributeOrderReasonQuery);
        logger.info("检查师傅不能被派单原因出参:[{}]", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            distributeReasonVO.setStatus(GlobalConsts.NO);
            distributeReasonVO.setReason("工程师信息错误");
            //logger.info("工程师信息错误");
            return;
        }

        EngineerSupportDistributeOrderDRO cannotDistributeOrderReasonDRO = responseDTO.getData();

        StringJoiner sj = new StringJoiner("；");

        // 基本条件检查没通过，返回接口定义的提示信息
        if (Objects.equals(cannotDistributeOrderReasonDRO.getDistributeOrderStatus(), GlobalConsts.NO)) {
            //distributeReasonVO.setStatus(GlobalConsts.NO);
            //distributeReasonVO.setReason(cannotDistributeOrderReasonDRO.getNotDistributeOrderEnum().getName());
            cannotDistributeOrderReasonDRO.getNotDistributeOrderList().forEach(e -> {
                sj.add(e.getName());
            });
            //logger.info("基本条件检查没通过，返回接口定义的提示信息");
            //return;
        }

        // 如果是返修单并且是原工程师，不检查了
        if (Objects.equals(distributeMasterQuery.getOrderType(), OrderConsts.ORDER_TYPE_REWORK)
                && distributeMasterQuery.getMasterId() != null && distributeMasterQuery.getMasterId() > 0
                && Objects.equals(distributeMasterQuery.getMasterId(), distributeMasterQuery.getOriginalMasterId())) {
            //logger.info("如果是返修单并且是原工程师，不检查了");
            if (sj.length() > 0) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason(sj.toString());
            }
            return;
        }

        // 不是C端订单，就不走下面的检查逻辑了
//            if (!Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
//                break;
//            }

        // 最大手头返修单：默认0
        int maxReworkCount = 0;

        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

            /*
            // 最大手头返修单没有设置，下面的检测逻辑就不走了
            if (maxReworkCount <= 0) {
                break;
            }
            */

        // 只查询当前工程师
        DistributeMasterQuery curDistributeMasterQuery = distributeMasterQuery;
        curDistributeMasterQuery.setMatchMasterIdList(Lists.newArrayList(distributeMasterQuery.getMasterId()));
        curDistributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        List<ZsOrderDistributeVO> masterList = this.listForUnrestrictedDistributeOrder(curDistributeMasterQuery);
        // PS:网格化差异点
        /*if (isGridDistribute) {
            masterList = this.listGridDistributeMasterByQuery(curDistributeMasterQuery);
        }
        else {
            masterList = this.listSpDistributeMasterByQuery(curDistributeMasterQuery);
        }*/

        // 查询失败
        if (CollectionUtils.isEmpty(masterList)) {
            distributeReasonVO.setStatus(GlobalConsts.NO);
            sj.add("没有查询到指定的工程师信息");
            distributeReasonVO.setReason(sj.toString());
            //logger.info("没有查询到指定的工程师信息");
            return;
        }

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        if (isGridDistribute) {
            // PS:网格化差异点，获取工程师列表网格信息
            this.getMasterListGridInfo(masterList, distributeMasterQuery);
        }

        // 检查基础条件
        Integer supportGridCountLimit = null;
        if (isGridDistribute) {
            supportGridCountLimit = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getSupportGridCountLimit();
        }

        this.checkBaseDistributeReason(masterList.get(0), distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj);
        /*if (StringUtil.isNotBlank(reason)) {
            distributeReasonVO.setStatus(GlobalConsts.NO);
            distributeReasonVO.setReason(reason);
            return;
        }*/

        // 如果是返修单或者开启新单简单派单，结束
        if (!Objects.equals(distributeMasterQuery.getOrderType(), OrderConsts.ORDER_TYPE_NEW) || simpleStatus) {
            if (sj.length() > 0) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason(sj.toString());
            }
            //logger.info("如果是返修单或者开启新单简单派单，结束");
            return;
        }

        // 调用工程师服务查询app位置在线和服务范围状态
        this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

        // 服务商派单，非直营工程师检查是否在线
        if (isGridDistribute) {
            masterList = this.onlineStatusFilter(masterList);
            if (CollectionUtils.isEmpty(masterList)) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                sj.add("非直营工程师App不在线");
                distributeReasonVO.setReason(sj.toString());
                //logger.info("非直营工程师App不在线");
                return;
            }
        }

        // 查询师傅统计信息并计算评分
        this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

        List<ZsOrderDistributeVO> inScopeMasterList = masterList;

        // PS:网格化差异点
        if (!isGridDistribute) {

            // 判断服务范围
            inScopeMasterList = this.scopeStatusFilter(masterList);

            if (CollectionUtils.isEmpty(inScopeMasterList)) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                sj.add("不在服务范围");
                distributeReasonVO.setReason(sj.toString());
                //logger.info("不在服务范围");
                return;
            }
        }

        // 检查推荐派单
        if (recommendStatus || fairStatus) {
            //logger.info("检查推荐派单");
            this.checkRecommendDistributeReason(inScopeMasterList, distributeMasterQuery, sj);
            /*if (reason != null) {
                distributeReasonVO.setStatus(GlobalConsts.NO);
                distributeReasonVO.setReason(reason);
            }*/

            return;
        }
    }

    /**
     * 存在服务中（已派单/已领单/已上门-进行中）相同位置、相同品类（前台二级产品分类）的其他工单 预约时间更相近工单的主工程师
     *
     * @param orderWork
     * @param orderDetail
     * @param isGridDistribute
     * @return
     */
    @Override
    public ZsOrderDistributeVO findDutyRecentMaster(OrderWork orderWork, OrderDetail orderDetail, boolean isGridDistribute) {

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, isGridDistribute);

        // 查询相似订单的师傅
        List<Integer> similarOrderMasterIds = this.getDistributedSimilarOrderMasterId(null, distributeMasterQuery);

        // 没有返回空
        if (CollectionUtils.isEmpty(similarOrderMasterIds)) {
            logger.info("#findDutyRecentMaster#:没有相似订单的师傅");
            return null;
        }

        // todo fubiao
        logger.info("findDutyRecentMaster#getEngineerDetailById 入参 [{}]",similarOrderMasterIds.get(0));
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(similarOrderMasterIds.get(0));
        logger.info("findDutyRecentMaster#getEngineerDetailById 出参 [{}]",JSON.toJSONString(cacheEngineerByEngineerId));
        if (!cacheEngineerByEngineerId.isSuccess() || cacheEngineerByEngineerId.getData() == null) {

            return null;
        }

        ZsOrderDistributeVO orderDistributeVO = new ZsOrderDistributeVO();
        orderDistributeVO.setMasterId(cacheEngineerByEngineerId.getData().getEngineerId());
        orderDistributeVO.setMasterName(cacheEngineerByEngineerId.getData().getRealName());
        orderDistributeVO.setMasterPhone(cacheEngineerByEngineerId.getData().getMobile());

        logger.info("#findDutyRecentMaster#:" + orderDistributeVO);
        return orderDistributeVO;
    }

    /**
     * 查询派单工程师
     */
    @Override
    public void getOrderDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {

        // 获取派单参数
        if (distributeArgsDRO == null) {
            distributeArgsDRO = this.getDistributeParam(orderWork);
        }

        // 按以下顺序处理：新单/返修，特殊/普通，CBF业务类型
        switch (orderWork.getType()) {

            // 新单
            case OrderConsts.ORDER_TYPE_NEW: {

                // 特殊派单
                if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_SPECIAL) {
                    switch (distributeVO.getSpecialDistributeType()) {
                        case OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_SP:
                            // 特殊服务商
                            this.getSpecialSpOrderDistributeMasterList(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                            break;
                        case OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_TMALL:
                            // 天猫差异派单
                            //this.getTmallOrderDistributeMasterList(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                            break;
//                        case OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_CHANNEL:
//                            // 渠道指定派单
//                            this.getChannelOrderDistributeMasterList(orderWork, orderDetail, distributeVO, distributeArgsDRO);
//                            break;
                    }
                }
                // 普通派单
                else {
                    if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                        this.getNewOrderDistributeMasterListTypeC(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                    } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                        this.getNewOrderDistributeMasterListTypeF(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                    }
                }

                break;
            }

            // 返修单
            case OrderConsts.ORDER_TYPE_REWORK: {
                if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                    this.getReworkOrderDistributeMasterListTypeC(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                    this.getReworkOrderDistributeMasterListTypeF(orderWork, orderDetail, distributeVO, distributeArgsDRO);
                }

                break;
            }

            default:
                break;
        }
    }

    /**
     * 天猫勤鸽店差异化派单查询工程师
     */

    private void getTmallOrderDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getTmallOrderDistributeMasterList");

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        if (distributeArgsDRO != null) {
            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 调用天猫勤鸽专用接口查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listTmallDistributeMasterByQuery(distributeMasterQuery);

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 基础条件过滤，目前就是判断最大返修单量
        masterList = this.baseDistributeFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, null);

        // 基础条件过滤后没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 过滤黑名单
        masterList = masterList.stream().filter(e -> !Objects.equals(e.getBlackList(), GlobalConsts.YES)).collect(Collectors.toList());

        // 过滤黑名单后没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 正常派单列表
        List<ZsOrderDistributeVO> recommendMasterList;

        do {

            // 没有特殊标识的订单，全部为正常派单，没有消耗派单
            if (!Objects.equals(distributeVO.getVipOrder(), GlobalConsts.YES)
                    && !Objects.equals(distributeVO.getBigPromotionOrder(), GlobalConsts.YES)) {
                recommendMasterList = masterList;
                masterList = Lists.newArrayListWithCapacity(0);
                break;
            }

            // 下面把masterList中符合条件的移动到正常派单列表
            recommendMasterList = Lists.newArrayListWithCapacity(masterList.size());

            Iterator<ZsOrderDistributeVO> it = masterList.iterator();

            while (it.hasNext()) {
                ZsOrderDistributeVO vo = it.next();

                // vip&&大促
                if (Objects.equals(distributeVO.getVipOrder(), GlobalConsts.YES)
                        && Objects.equals(distributeVO.getBigPromotionOrder(), GlobalConsts.YES)) {
                    if (Objects.equals(vo.getVip(), GlobalConsts.YES)
                            && Objects.equals(vo.getBigPromotion(), GlobalConsts.YES)) {
                        recommendMasterList.add(vo);
                        it.remove();
                    }
                }
                // vip
                else if (Objects.equals(distributeVO.getVipOrder(), GlobalConsts.YES)) {
                    if (Objects.equals(vo.getVip(), GlobalConsts.YES)) {
                        recommendMasterList.add(vo);
                        it.remove();
                    }
                }
                // 大促
                else {
                    if (Objects.equals(vo.getBigPromotion(), GlobalConsts.YES)) {
                        recommendMasterList.add(vo);
                        it.remove();
                    }
                }

            }

        } while (false);

        // 保存消耗派单列表
        distributeVO.setMasterList(masterList);
        // 保存正常派单列表
        distributeVO.setRecommendMasterList(recommendMasterList);
    }

    /**
     * 查询新单派单工程师 Type C
     */
    private void getNewOrderDistributeMasterListTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getNewOrderDistributeMasterListTypeC");

        /// 后门开关：默认打开
        boolean backdoorStatus = true;
        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        if (distributeArgsDRO != null) {
//            if (Objects.equals(distributeArgsDRO.getBackdoorStatus(), GlobalConsts.NO)) {
//                backdoorStatus = false;
//            }

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);

        if (backdoorStatus) {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
        } else {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.NO);
        }

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 初始化派单快照:不可派单列表
        distributeVO.setNonDistributeMasterList(Lists.newArrayListWithCapacity(masterList.size()));

        // 调用工程师服务查询app位置在线和服务范围状态
        this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 基础条件过滤，目前就是判断最大返修单量
        masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, null, distributeVO.getNonDistributeMasterList());

        // 基础条件过滤后没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 计算距离
        this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

        // 按主技能和手头单量排序
        this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

        // 只查询基础师傅列表，结束
        if (distributeVO.isOnlyBaseMasterList()) {

            // 保存简单派单师傅
            if (distributeVO.isSimpleStatus()) {
                distributeVO.setMasterList(masterList);
            }

            return;
        }

        // 非简单派单模式
        if (!distributeVO.isSimpleStatus()) {
            // 检查非直营工程师是否在线
            masterList = this.onlineStatusSnapshotFilter(masterList, distributeVO.getNonDistributeMasterList());

            // 过滤后没有工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                return;
            }
        }

        // 查询师傅统计信息并计算评分
        this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);
        //logger.info("calcRecommendScore：" + masterList);

        List<ZsOrderDistributeVO> recommendMasterList = null;

        if (distributeVO.isRecommendStatus() || distributeVO.isFairStatus()) {

            // 只保留服务范围内的工程师
            List<ZsOrderDistributeVO> inScopeMasterList = this.scopeStatusSnapshotFilter(masterList, distributeVO.getNonDistributeMasterList());

            if (CollectionUtils.isNotEmpty(inScopeMasterList)) {
                if (distributeVO.isRecommendStatus()) {
                    // 推荐列表
                    recommendMasterList = this.getSortScoreMasterList(inScopeMasterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                } else if (distributeVO.isFairStatus()) {
                    // 公平列表
                    recommendMasterList = this.getSortFairMasterList(inScopeMasterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                }
            }
        }

        //logger.info("#recommendMasterList#:" + recommendMasterList);
        distributeVO.setRecommendMasterList(recommendMasterList);

        /*
        // 加载"非离职+技能+服务范围"的工程师（把上方满足条件的工程师排除在外）
        List<ZsOrderDistributeVO> nonDistributeMasterList = this.listNonDistributeMaster(recommendMasterList, distributeMasterQuery);
        distributeVO.setNonDistributeMasterList(nonDistributeMasterList);
        */

        // 保存简单派单师傅
        if (distributeVO.isSimpleStatus()) {
            distributeVO.setMasterList(masterList);
        }

    }

    /**
     * 查询新单派单工程师 Type F
     */
    private void getNewOrderDistributeMasterListTypeF(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getNewOrderDistributeMasterListTypeF");

        /// 后门开关：默认打开
        boolean backdoorStatus = true;

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);

        if (backdoorStatus) {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
        } else {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.NO);
        }

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 按主技能和手头单量排序
        this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

        // 保存简单派单师傅
        if (distributeVO.isSimpleStatus()) {
            distributeVO.setMasterList(masterList);
        }

    }

    /**
     * 查询返修单派单工程师 Type C
     */
    private void getReworkOrderDistributeMasterListTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getReworkOrderDistributeMasterListTypeC");

        // 返修原单工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        distributeVO.setReworkMasterId(reworkMasterId);

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        if (distributeArgsDRO != null) {
            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 查询原工程师
        ZsOrderDistributeVO reworkMaster = null;

        if (reworkMasterId != null && reworkMasterId > 0) {
            reworkMaster = this.findDistributeOrderByOriginalMaster(orderWork, distributeVO.getReworkMasterId(), false);
        }

        // 查询非原单工程师外的其他工程师
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 如果有返修原工程师，列表中排除原工程师
        if (reworkMasterId != null && reworkMasterId > 0) {
            List<Integer> excludeMasterIdList = new ArrayList<>(1);
            excludeMasterIdList.add(reworkMasterId);
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        // 查询其他工程师列表
        List<ZsOrderDistributeVO> masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

        // 处理返修工程师列表
        this.procReworkMasterList(distributeVO, reworkMaster, masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount,null);
    }

    /**
     * 查询返修单派单工程师 Type F
     */
    private void getReworkOrderDistributeMasterListTypeF(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getReworkOrderDistributeMasterListTypeF");

        // 返修原单工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        distributeVO.setReworkMasterId(reworkMasterId);

        // 查询原工程师
        ZsOrderDistributeVO reworkMaster = null;

        if (reworkMasterId != null && reworkMasterId > 0) {
            reworkMaster = this.findDistributeOrderByOriginalMaster(orderWork, distributeVO.getReworkMasterId(), false);
        }

        // 查询非原单工程师外的其他工程师
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 如果有返修原工程师，列表中排除原工程师
        if (reworkMasterId != null && reworkMasterId > 0) {
            List<Integer> excludeMasterIdList = new ArrayList<>(1);
            excludeMasterIdList.add(reworkMasterId);
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        // 查询其他工程师列表
        List<ZsOrderDistributeVO> masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

        // 处理返修工程师列表
        this.procReworkMasterList(distributeVO, reworkMaster, masterList, distributeMasterQuery, 0, 0, null);
    }

    /**
     * 查询特殊服务商派单工程师
     */
    private void getSpecialSpOrderDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
        logger.info("getSpecialSpOrderDistributeMasterList");

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listSpecialSpDistributeMasterByQuery(distributeMasterQuery);

        // 返回给VO
        distributeVO.setMasterList(masterList);
    }

    /**
     * 查询渠道指定派单工程师
     */
//    private void getChannelOrderDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeArgsDRO distributeArgsDRO) {
//        logger.info("查询渠道指定派单工程师");
//
//        // 构建查询
//        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
//
//        // 查询工程师列表
//        List<ZsOrderDistributeVO> masterList = this.listChannelDistributeMasterByQuery(distributeMasterQuery);
//
//        // 返回给VO
//        distributeVO.setMasterList(masterList);
//    }

    /**
     * 查询基础工程师列表(师傅状态(包含停单中和请假中),不判断在线状态，服务范围)
     */
    @Override
    public List<ZsOrderDistributeVO> listBaseDistributeMaster(OrderWork orderWork, OrderDetail orderDetail) {

        // 查询基础工程师列表
        List<ZsOrderDistributeVO> masterList = null;

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        // 获取派单参数
        DistributeArgsDRO distributeArgsDRO = this.getDistributeParam(orderWork);
        if (distributeArgsDRO != null) {
            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 查询工程师列表
        do {

            // 保存预约时间用于动态库存查询
            Date dutyTime = orderWork.getDutyTime();

            // 查询所有符合条件的工程师
            DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
            // 师傅状态(包含停单中和请假中)
            distributeMasterQuery.setDutyTime(null);
            // 不判断在线状态，服务范围
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
            // 不校验服务公司
            distributeMasterQuery.setManageCompanyId(null);

            masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);
            if (CollectionUtils.isEmpty(masterList)) {
                break;
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            // 基础条件过滤
            masterList = this.baseDistributeFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount,null);
        } while (false);

        if (masterList == null) {
            masterList = Lists.newArrayListWithCapacity(0);
        }

        return masterList;
    }

    /**
     * 调用工程师dubbo获取派单工程师列表
     *
     * @param distributeMasterQuery
     * @return
     */
    @Override
    public List<ZsOrderDistributeVO> listSpDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());

        return this.listSpDistributeMasterByQuery(distributeMasterQuery, servSkillLists);
    }

    private List<ZsOrderDistributeVO> listSpDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery, List<List<DistributeOrderSkillQuery>> servSkillLists) {

        // 生成调用参数
        //DistributeOrderQuery distributeOrderQuery = new DistributeOrderQuery();
        EngineerGeneralDistributeOrderQuery distributeOrderQuery = new EngineerGeneralDistributeOrderQuery();

        distributeOrderQuery.setSerialNumber(UUID.randomUUID().toString());

        //distributeOrderQuery.setBackDoorStatus(distributeMasterQuery.getBackdoorStatus());
        distributeOrderQuery.setSkipServAreaCheck(distributeMasterQuery.getBackdoorStatus());
        distributeOrderQuery.setSkipOnlineCheck(distributeMasterQuery.getBackdoorStatus());
        distributeOrderQuery.setCooperationType(distributeMasterQuery.getAgent());
        distributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
        distributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
        distributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
        distributeOrderQuery.setCityId(distributeMasterQuery.getCityId());
        distributeOrderQuery.setCountyId(distributeMasterQuery.getCountyId());
        if (Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_NONE) ||
                Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_DEFAULT)) {
            distributeOrderQuery.setStreetId(distributeMasterQuery.getStreetId());
        } else {
            distributeOrderQuery.setStreetId(0);
        }
        distributeOrderQuery.setSubCompanyId(distributeMasterQuery.getCompanyId());
        distributeOrderQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
        distributeOrderQuery.setOrderLat(distributeMasterQuery.getLatitude());
        distributeOrderQuery.setOrderLng(distributeMasterQuery.getLongitude());
        distributeOrderQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        distributeOrderQuery.setServCategId(distributeMasterQuery.getServCategId());
        distributeOrderQuery.setCategId(distributeMasterQuery.getShowCategId());
        distributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());

        distributeOrderQuery.setMatchEngineerList(distributeMasterQuery.getMatchMasterIdList());
        distributeOrderQuery.setExcludeEngineerList(distributeMasterQuery.getExcludeMasterIdList());

        // 后台技能
        distributeOrderQuery.setServSkillList(servSkillLists);
        // 最大试用周期
        distributeOrderQuery.setMaxProbationCycle(7);

        // 调用查询派单工程师接口
        //logger.info("listDistributeOrderMaster：{}", distributeOrderQuery);
        // todo fubiao
        logger.info("listSpDistributeMasterByQuery#listForGeneralDistributeOrder 入参 [{}] ",JSON.toJSONString(distributeOrderQuery));
        ResponseDTO<List<EngineerDistributeOrderDRO>> responseDTO = spDistributeOrderListRemoteService.listForGeneralDistributeOrder(distributeOrderQuery);
        logger.info("listSpDistributeMasterByQuery#listForGeneralDistributeOrder 出参 [{}]",JSON.toJSONString(responseDTO));
        //logger.info("listDistributeOrderMaster[responseDTO]：{}", responseDTO);

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngineerDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();

        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }

    /**
     * 查询工程师派单参数
     * @param distributeMasterQuery
     * @return
     */
    private List<ZsOrderDistributeVO> listForUnrestrictedDistributeOrder(DistributeMasterQuery distributeMasterQuery) {

        // 生成调用参数
        EngineerUnrestrictedDistributeOrderQuery distributeOrderQuery = new EngineerUnrestrictedDistributeOrderQuery();

        distributeOrderQuery.setSerialNumber(UUID.randomUUID().toString());
        distributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
        distributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
        distributeOrderQuery.setServCategId(distributeMasterQuery.getServCategId());
        distributeOrderQuery.setCategId(distributeMasterQuery.getShowCategId());
        distributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());
        distributeOrderQuery.setMatchEngineerList(distributeMasterQuery.getMatchMasterIdList());

        // 调用查询派单工程师接口
        logger.info("listForUnrestrictedDistributeOrder 入参 [{}] ",JSON.toJSONString(distributeOrderQuery));
        ResponseDTO<List<EngineerDistributeOrderDRO>> responseDTO = spDistributeOrderListRemoteService.listForUnrestrictedDistributeOrder(distributeOrderQuery);
        logger.info("listForUnrestrictedDistributeOrder 出参 [{}]",JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngineerDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();

        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }

    /**
     * 调用工程师dubbo获取天猫勤鸽店派单工程师列表
     *
     * @param distributeMasterQuery
     * @return
     */
    @Deprecated  // 废弃不使用了 天猫的
    private List<ZsOrderDistributeVO> listTmallDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {

//        // 生成调用参数
//        DistributeOrderQuery distributeOrderQuery = new DistributeOrderQuery();
//
//        distributeOrderQuery.setBackDoorStatus(distributeMasterQuery.getBackdoorStatus());
//        distributeOrderQuery.setAgent(distributeMasterQuery.getAgent());
//        distributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
//        distributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
//        distributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
//        distributeOrderQuery.setCityId(distributeMasterQuery.getCityId());
//        distributeOrderQuery.setCountyId(distributeMasterQuery.getCountyId());
//        if (Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_NONE) ||
//                Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_DEFAULT)) {
//            distributeOrderQuery.setStreetId(distributeMasterQuery.getStreetId());
//        } else {
//            distributeOrderQuery.setStreetId(0);
//        }
//        distributeOrderQuery.setCompanyId(distributeMasterQuery.getCompanyId());
//        distributeOrderQuery.setManageCompanyId(distributeMasterQuery.getManageCompanyId());
//        distributeOrderQuery.setOrderLat(distributeMasterQuery.getLatitude());
//        distributeOrderQuery.setOrderLng(distributeMasterQuery.getLongitude());
//        distributeOrderQuery.setDutyTime(distributeMasterQuery.getDutyTime());
//        distributeOrderQuery.setServCategId(distributeMasterQuery.getServCategId());
//        distributeOrderQuery.setShowCategId(distributeMasterQuery.getShowCategId());
//        distributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());
//        distributeOrderQuery.setMatchMasterIdList(distributeMasterQuery.getMatchMasterIdList());
//        distributeOrderQuery.setExcludeMasterIdList(distributeMasterQuery.getExcludeMasterIdList());
//
//        // 后台技能
//        //List<List<com.zmn.biz.engineer.common.query.distribute.DistributeOrderSkillQuery >> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
//          //      distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
//       // distributeOrderQuery.setServSkillLists(servSkillLists);
//
//        // 调用查询派单工程师接口
//        logger.info("listDistributeOrderMasterExpand：" + distributeOrderQuery);
//        // todo listDistributeOrderMasterExpand
//        //engDistributeOrderListRemoteService.listDistributeOrderMasterExpand(distributeOrderQuery);
//        ResponseDTO<List<EngDistributeOrderExpandDRO>> responseDTO = new ResponseDTO<>();
//        logger.info("listDistributeOrderMasterExpand[responseDTO]：" + responseDTO);
//
//        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
//            return Lists.newArrayListWithCapacity(0);
//        }
//
//        List<EngDistributeOrderExpandDRO> distributeOrderDROList = responseDTO.getData();
//        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
//            return Lists.newArrayListWithCapacity(0);
//        }
//
//        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
//        distributeOrderDROList.forEach((item) -> {
//            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
//
//            // 天猫勤鸽店派单工程师附加信息
//            vo.setAbilityList(BeanMapper.mapList(item.getAbilityList(), ZsOrderDistributeExpandAbilityVO.class));
//            vo.setBigPromotion(item.getBigPromotion());
//            vo.setBlackList(item.getBlackList());
//            vo.setDegradation(item.getDegradation());
//            vo.setVip(item.getVip());
//
//            distributeMasterList.add(vo);
//        });

        return Lists.newArrayList();
    }

    /**
     * 调用工程师dubbo获取特殊服务商派单工程师列表
     *
     * @param distributeMasterQuery
     * @return
     */
    private List<ZsOrderDistributeVO> listSpecialSpDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {

        // 生成调用参数
        //SpDistributeOrderQuery spDistributeOrderQuery = new SpDistributeOrderQuery();
        EngineerSpecialDistributeOrderQuery spDistributeOrderQuery = new EngineerSpecialDistributeOrderQuery();

        spDistributeOrderQuery.setSerialNumber(UUID.randomUUID().toString());

        spDistributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
        spDistributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
        spDistributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
        spDistributeOrderQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
        spDistributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());

        // 调用查询派单工程师接口
        // todo fubiao
        logger.info("listSpecialSpDistributeMasterByQuery#listForSpecialDistributeOrder 入参 [{}]" + JSON.toJSONString(spDistributeOrderQuery));
        ResponseDTO<List<EngineerDistributeOrderDRO>> responseDTO = spDistributeOrderListRemoteService.listForSpecialDistributeOrder(spDistributeOrderQuery);
        logger.info("listSpecialSpDistributeMasterByQuery#listForSpecialDistributeOrder 出参 [{}]",JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngineerDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();
        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }

    /**
     * 调用工程师dubbo获取渠道指定派单工程师列表
     *
     * @param
     * @return
     */
//    private List<ZsOrderDistributeVO> listChannelDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {
//
//        // 生成调用参数
//        ChannelDistributeOrderQuery channelDistributeOrderQuery = new ChannelDistributeOrderQuery();
//
//        channelDistributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
//        channelDistributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
//        channelDistributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
//        channelDistributeOrderQuery.setProvinceId(distributeMasterQuery.getProvinceId());
//        channelDistributeOrderQuery.setCityId(distributeMasterQuery.getCityId());
//        channelDistributeOrderQuery.setCompanyId(distributeMasterQuery.getCompanyId());
//        channelDistributeOrderQuery.setManageCompanyId(distributeMasterQuery.getManageCompanyId());
//
//        // 调用查询派单工程师接口
//        logger.info("listChannelDistributeOrderMaster：" + channelDistributeOrderQuery);
//        ResponseDTO<List<EngDistributeOrderDRO>> responseDTO = engDistributeOrderListRemoteService.listChannelDistributeOrderMaster(channelDistributeOrderQuery);
//        logger.info("listChannelDistributeOrderMaster[responseDTO]：" + responseDTO);
//
//        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
//            return Lists.newArrayListWithCapacity(0);
//        }
//
//        List<EngDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();
//        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
//            return Lists.newArrayListWithCapacity(0);
//        }
//
//        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
//        distributeOrderDROList.forEach((item) -> {
//            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
//            distributeMasterList.add(vo);
//        });
//
//        return distributeMasterList;
//    }

    // 调用工程师dubbo查询原单工程师可否派单
    private ZsOrderDistributeVO findDistributeOrderByOriginalMaster(OrderWork orderWork, Integer reworkMasterId, boolean isGridDistribute) {
        ZsOrderDistributeVO reworkMaster = null;

        EngineerReworkDistributeOrderQuery repairDistributeOrderQuery = new EngineerReworkDistributeOrderQuery();

        repairDistributeOrderQuery.setSerialNumber(UUID.randomUUID().toString());

        repairDistributeOrderQuery.setPlat(orderWork.getPlatWork());
        repairDistributeOrderQuery.setBizType(orderWork.getBizType());
        repairDistributeOrderQuery.setChannelId(orderWork.getChannelId());

        if (!isGridDistribute) {
            // 服务商派单查询条件使用返修原单的公司和服务商
            repairDistributeOrderQuery.setSubCompanyId(orderWork.getCompanyId());
            repairDistributeOrderQuery.setSpCompanyId(orderWork.getManageCompanyId());
        }

        repairDistributeOrderQuery.setCityId(orderWork.getCityId());
        repairDistributeOrderQuery.setDutyTime(orderWork.getDutyTime());
        repairDistributeOrderQuery.setServCategId(orderWork.getServCategId());
        repairDistributeOrderQuery.setCategId(orderWork.getShowCategId());
        repairDistributeOrderQuery.setProductGroupId(orderWork.getServProductGroupId());
        repairDistributeOrderQuery.setOriginalEngineerId(reworkMasterId);

        //logger.info("getRepairDistributeOrderEngineer：" + repairDistributeOrderQuery);
        // todo fubiao
        logger.info("findDistributeOrderByOriginalMaster#getForReworkDistributeOrder 入参 [{}]",JSON.toJSONString(repairDistributeOrderQuery));
        ResponseDTO<EngineerDistributeOrderDRO> responseDTO = spDistributeOrderListRemoteService.getForReworkDistributeOrder(repairDistributeOrderQuery);
        logger.info("findDistributeOrderByOriginalMaster#getForReworkDistributeOrder 出参 [{}]",JSON.toJSONString(responseDTO));
        //logger.info("getRepairDistributeOrderEngineer：" + responseDTO);

        if (responseDTO.isSuccess() && responseDTO.getData() != null) {
            reworkMaster = this.transformDistributeObjectDRO2VO(responseDTO.getData());
        }

        return reworkMaster;
    }

    /*
    // 加载"非离职+技能+服务范围"的工程师（把满足条件的工程师排除在外）
    private List<ZsOrderDistributeVO> listNonDistributeMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 设置DIO参数
        NonDistributeOrderQuery nonDistributeOrderQuery = new NonDistributeOrderQuery();
        nonDistributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
        nonDistributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
        nonDistributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
        nonDistributeOrderQuery.setCityId(distributeMasterQuery.getCityId());
        nonDistributeOrderQuery.setCountyId(distributeMasterQuery.getCountyId());
        if (Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_NONE) ||
                Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_DEFAULT)) {
            nonDistributeOrderQuery.setStreetId(distributeMasterQuery.getStreetId());
        } else {
            nonDistributeOrderQuery.setStreetId(0);
        }
        nonDistributeOrderQuery.setCompanyId(distributeMasterQuery.getCompanyId());
        nonDistributeOrderQuery.setManageCompanyId(distributeMasterQuery.getManageCompanyId());
        nonDistributeOrderQuery.setOrderLat(distributeMasterQuery.getLatitude());
        nonDistributeOrderQuery.setOrderLng(distributeMasterQuery.getLongitude());
        nonDistributeOrderQuery.setServCategId(distributeMasterQuery.getServCategId());
        nonDistributeOrderQuery.setShowCategId(distributeMasterQuery.getShowCategId());
        nonDistributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());

        // 排除当前可派单工程师
        if (CollectionUtils.isNotEmpty(masterList)) {
            List<Integer> excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
            nonDistributeOrderQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        // 后台技能
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
        nonDistributeOrderQuery.setServSkillLists(servSkillLists);

        logger.info("listNonDistributeOrderMaster：" + nonDistributeOrderQuery);
        ResponseDTO<List<EngDistributeOrderDRO>> responseDTO = engDistributeOrderListRemoteService.listNonDistributeOrderMaster(nonDistributeOrderQuery);
        logger.info("listNonDistributeOrderMaster：" + responseDTO);

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();
        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }
*/

    // 获取工程师在线及服务范围状态信息
    private void getMasterOnlineStatusAndScopeStatus(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return;
        }

        // 工程师id列表
        List<Integer> masterIds = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());

        // 调用获取工程师在线及服务范围状态信息dubbo
        EngineerServScopeStatusQuery engineerOnlineStatusAndScopeStatusDIO = new EngineerServScopeStatusQuery();

        Set<Integer> integerSet = new HashSet<>(masterIds);
        engineerOnlineStatusAndScopeStatusDIO.setEngineerIdSet(integerSet);
        engineerOnlineStatusAndScopeStatusDIO.setCityId(distributeMasterQuery.getCityId());
        engineerOnlineStatusAndScopeStatusDIO.setCountyId(distributeMasterQuery.getCountyId());
        if (Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_NONE) ||
                Objects.equals(distributeMasterQuery.getStreetSource(), OrderConsts.STREET_SOURCE_DEFAULT)) {
            engineerOnlineStatusAndScopeStatusDIO.setStreetId(distributeMasterQuery.getStreetId());
        } else {
            engineerOnlineStatusAndScopeStatusDIO.setStreetId(0);
        }
        engineerOnlineStatusAndScopeStatusDIO.setLon(distributeMasterQuery.getLongitude());
        engineerOnlineStatusAndScopeStatusDIO.setLat(distributeMasterQuery.getLatitude());

        //logger.info("checkEngineerOnlineStatusAndScopeStatus：" + engineerOnlineStatusAndScopeStatusDIO);
        // todo checkEngineerOnlineStatusAndScopeStatus
        // todo fubiao
        logger.info("getMasterOnlineStatusAndScopeStatus#listEngineerServAreaScopeStatusByQuery 入参 [{}]",JSON.toJSONString(engineerOnlineStatusAndScopeStatusDIO));
        ResponseDTO<List<EngineerServScopeStatusDRO>> responseDTO = engineerServAreaListRemoteService.listEngineerServAreaScopeStatusByQuery(engineerOnlineStatusAndScopeStatusDIO);
        logger.info("getMasterOnlineStatusAndScopeStatus#listEngineerServAreaScopeStatusByQuery 出参 [{}]",JSON.toJSONString(responseDTO));
        //logger.info("checkEngineerOnlineStatusAndScopeStatus[responseDTO]：" + responseDTO);

        if (!responseDTO.isSuccess()) {
            return;
        }

        List<EngineerServScopeStatusDRO> statusList = responseDTO.getData();
        if (CollectionUtils.isEmpty(statusList)) {
            return;
        }

        // 设置状态到每一个vo对象
        Map<Integer, ZsOrderDistributeVO> masterMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));

        statusList.forEach(item -> {
            ZsOrderDistributeVO vo = masterMap.get(item.getEngineerId());
            if (vo != null) {
                vo.setOnlineStatus(item.getOnlineStatus());
                vo.setScopeStatus(item.getScopeStatus());

                if (!Objects.equals(GlobalConsts.YES, vo.getOnlineStatus())) {
                    vo.setMasterLng(null);
                    vo.setMasterLat(null);
                }
            }
        });
    }

    /**
     * 自动派单
     *
     * @param orderWork
     */
    @Override
    public boolean autoDistribute(OrderWork orderWork, Integer masterId) throws OmsBaseException {
        return this.autoDistribute(orderWork, masterId, 0);
    }

    private boolean autoDistribute(OrderWork orderWork, Integer masterId, int autoDistributeCount) throws OmsBaseException {

        // 先处理录单预派
        boolean preDistribute = true;
        OrderChangeRecord orderChangeRecord = orderChangeRecordService.getChangeRecordByOrderId(orderWork.getOrderId());
        if (orderChangeRecord != null && orderChangeRecord.getFirstDistributeTime() != null) {
            preDistribute = false;
        }

        if (preDistribute) {
            PlaceAnOrderPreDistribute placeAnOrderPreDistribute = getPlaceAnOrderDistribute(orderWork.getWorkId());
            if (placeAnOrderPreDistribute != null) {
                return this.autoPreDistribute(placeAnOrderPreDistribute, orderWork);
            }
        }

        // 自动派单时间
        Date date = DateUtil.getNow();

        // 派单快照
        DistributeVO distributeSnapshotVO = new DistributeVO();
        distributeSnapshotVO.setAutoDistributeTime(date);
        boolean ret = false;

        do {

            // 测试单不自动派单
            if (Objects.equals(orderWork.getTest(), GlobalConsts.YES)) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_TEST);
                break;
            }

            //  待取消，不允许自动派单 （新版跟单）
            Integer waitCancelStatus = workTrackBService.getUserWaitCancelStatus(orderWork.getOrderId(), orderWork.getWorkId());
            if (Objects.equals(waitCancelStatus, GlobalConsts.YES)) {
                this.saveNonDistributeOrderLog(null, orderWork, null, "用户取消申请，不可派单");
                break;
            }

            CancelApplyResultBO cancelApplyResultBO = cancelApplyBService.getWaitCancelInfo(orderWork.getOrderId(), orderWork.getWorkId());
            if (Objects.equals(cancelApplyResultBO.getUserWaitCancelStatus(), GlobalConsts.YES) || Objects.equals(cancelApplyResultBO.getMasterWaitCancelStatus(), GlobalConsts.YES)) {
                this.saveNonDistributeOrderLog(null, orderWork, null, "取消申请进行中，不可派单");
                break;
            }

            TrackWorkQuery query = new TrackWorkQuery();
            query.setOrderId(orderWork.getOrderId());
            query.setWorkId(orderWork.getWorkId());
            query.setNotStatus(TrackConsts.TRACK_STATUS_FINISHED);
            query.setPromoterTypeList(Lists.newArrayList(GlobalConsts.OPERATE_USER_TYPE_USER, GlobalConsts.OPERATE_USER_TYPE_MASTER));
            query.setNotTrackContentId(TrackConsts.TRACK_CONTENT_ID_REMINDER);
            ResponseDTO<Integer> listResponseDTO = trackWorkListRemoteService.countTrackByQuery(query);
            if (listResponseDTO.isSuccess() && listResponseDTO.getData() > 0) {
                this.saveNonDistributeOrderLog(null, orderWork, null, "有待处理跟单，不可派单");
                break;
            }

            // 特殊渠道不自动派单：10777京东服务+，41837
            /*if (Objects.equals(orderWork.getChannelId(), 10777)
                    || Objects.equals(orderWork.getChannelId(), 41837)) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SPECIAL_CHANNEL);
                break;
            }*/

            // 渠道是否配置了自动派单
            ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
            if (confOrderChannelDRO != null && !Objects.equals(confOrderChannelDRO.getAutoDistributeOrder(), com.zmn.consts.GlobalConsts.YES)) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SPECIAL_CHANNEL);
                break;
            }

            // 获取派单配置
            DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
            if (distributeConfigDRO == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
                break;
            }

            // 配置为网格化派单
            if (this.isGridDistribute(orderWork)) {

                if (distributeConfigDRO.getPlatDirectlyDistributeArgsDRO() == null) {
                    distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
                    break;
                }

                // 网格化自动派单
                ret = this.gridAutoDistribute(orderWork, masterId, autoDistributeCount, distributeConfigDRO, distributeSnapshotVO);
                distributeSnapshotVO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
                break;
            }

            if (distributeConfigDRO.getDistributeArgsDRO() == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
                break;
            }

            // 服务商自动派单
            ret = this.spAutoDistribute(orderWork, masterId, autoDistributeCount, distributeConfigDRO.getDistributeArgsDRO(), distributeSnapshotVO);
            distributeSnapshotVO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);

        } while (false);

        // 保存派单快照

        do {

            // 自动派单成功
            if (distributeSnapshotVO.getDistributeRule() != null && distributeSnapshotVO.getDistributeRule() > 0) {

                if (OrderDistributeConsts.distributeSnapshotList.contains(distributeSnapshotVO.getDistributeRule())) {
                    DistributeSnapshot distributeSnapshot = BeanMapper.map(distributeSnapshotVO, DistributeSnapshot.class);
                    distributeSnapshot.setWorkId(orderWork.getWorkId());
                    distributeSnapshot.setSnapshotId(Long.valueOf(DateUtil.dateFormatToString(date, FORMAT_DATETIME4)));
                    if (StringUtil.isBlank(distributeSnapshot.getDistributeRuleName())) {
                        distributeSnapshot.setDistributeRuleName(OrderDistributeConsts.getDistributeRuleName(
                                distributeSnapshot.getDistributeRule()));
                    }
                    distributeSnapshot.setDistributeWayName(OrderDistributeConsts.getDistributeWayName(
                            distributeSnapshot.getDistributeWay()));
                    distributeSnapshot.setCreateTime(date);
                    this.addDistributeSnapshot(distributeSnapshot);
                }

                break;
            }

            // 不能自动派单有原因
            if (distributeSnapshotVO.getDistributeRule() != null && distributeSnapshotVO.getDistributeRule() < 0) {
                // 不能自动派单有师傅列表
                if (CollectionUtil.isNotNullOrEmpty(distributeSnapshotVO.getNonDistributeMasterList())) {
                    if (OrderDistributeConsts.distributeSnapshotList.contains(distributeSnapshotVO.getDistributeRule())) {
                        DistributeSnapshot distributeSnapshot = BeanMapper.map(distributeSnapshotVO, DistributeSnapshot.class);
                        distributeSnapshot.setWorkId(orderWork.getWorkId());
                        distributeSnapshot.setSnapshotId(Long.valueOf(DateUtil.dateFormatToString(date, FORMAT_DATETIME4)));
                        distributeSnapshot.setDistributeRuleName(OrderDistributeConsts.getDistributeRuleName(
                                distributeSnapshot.getDistributeRule()));
                        distributeSnapshot.setDistributeWayName(OrderDistributeConsts.getDistributeWayName(
                                distributeSnapshot.getDistributeWay()));
                        distributeSnapshot.setCreateTime(date);
                        this.addDistributeSnapshot(distributeSnapshot);
                    }
                }
                // 保存日志
                this.saveNonDistributeOrderLog(distributeSnapshotVO, orderWork, date, null);
                break;
            }

            // 不能自动派单有师傅列表
            if (CollectionUtils.isNotEmpty(distributeSnapshotVO.getNonDistributeMasterList())) {
                // 保存快照
                DistributeSnapshot distributeSnapshot = BeanMapper.map(distributeSnapshotVO, DistributeSnapshot.class);
                distributeSnapshot.setWorkId(orderWork.getWorkId());
                distributeSnapshot.setSnapshotId(Long.valueOf(DateUtil.dateFormatToString(date, FORMAT_DATETIME4)));
                distributeSnapshot.setDistributeWayName(OrderDistributeConsts.getDistributeWayName(
                        distributeSnapshot.getDistributeWay()));
                distributeSnapshot.setCreateTime(date);
                this.addDistributeSnapshot(distributeSnapshot);
                // 保存日志
                this.saveNonDistributeOrderLog(distributeSnapshotVO, orderWork, date, null);
                break;
            }

        } while (false);

        return ret;
    }

    // 服务商自动派单
    private boolean spAutoDistribute(OrderWork orderWork, Integer masterId, int autoDistributeCount, DistributeArgsDRO distributeArgsDRO, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("服务商自动派单:workId=" + orderWork.getWorkId());

        // 获取派单参数
        if (distributeArgsDRO == null) {
            // 获取派单参数失败，不自动派单，结束
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
            return false;
        }

        // 自动派单操作计次+1
        autoDistributeCount++;

        // 删除自动派单存根
        this.delAutoDistributeStub(orderWork.getWorkId());

        // 1.统一判断逻辑

        // 1.1 不是进行中的单不处理
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_STATUS);
            return false;
        }

        // 1.2 非已分单的状态不处理
        if (!Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_ASSIGN)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_STATUS);
            return false;
        }

        // 1.3 挂起状态，不自动派单
        if (Objects.equals(orderWork.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SUSPEND);
            return false;
        }

        // 1.4 工单设置为不自动派单
        if (Objects.equals(orderWork.getAutoDistribute(), GlobalConsts.NO)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            return false;
        }

        // 订单详情
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        // 工单联系人姓名不规范，不自动派单
        if (StringUtils.isBlank(orderDetail.getContactName())) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_USER_INFO);
            return false;
        }

        // 派单视图
        DistributeVO distributeVO = this.buildDistributeVO(orderWork, orderDetail, distributeArgsDRO);

        // 1.4.特殊派单，不自动派单
        if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_SPECIAL) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SPECIAL);
            return false;
        }

        // 2.以下按业务类型区分处理

        // 2.1 C端订单没有预约时间，不自动派单
        if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            if (orderWork.getDutyTime() == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_DUTY_TIME);
                return false;
            }
        }

        // 不是师傅加单，判断自动派单参数
        if (masterId == null) {
            switch (orderWork.getType()) {
                case OrderConsts.ORDER_TYPE_NEW: // 新单

                    // 没有配置新单自动派单，结束
                    if (distributeArgsDRO.getAutoStatusNew() == null
                            || Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)) {
                        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
                        return false;
                    }

                    break;

                case OrderConsts.ORDER_TYPE_REWORK: // 返修单

                    // 没有配置返修单自动派单，结束
                    if (!Objects.equals(distributeArgsDRO.getAutoStatusRework(), GlobalConsts.YES)) {
                        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
                        return false;
                    }

                    break;

                default:
                    return false;
            }
        }

        // 默认自动派单起止时间
        String autoTimeStart = "7:30";
        String autoTimeEnd = "21:30";

        if (StringUtils.isNotBlank(distributeArgsDRO.getAutoTimeStart()) && StringUtils.isNotBlank(distributeArgsDRO.getAutoTimeEnd())) {
            autoTimeStart = distributeArgsDRO.getAutoTimeStart();
            autoTimeEnd = distributeArgsDRO.getAutoTimeEnd();
        }

        // 不在可派单时间范围内，不自动派单，师傅加单不受约束
        if (masterId == null) {
            Date curTime = DateUtil.getNow();
            int intCurTime = curTime.getHours() * 100 + curTime.getMinutes();

            String[] strStartTime = autoTimeStart.split(":");
            int intStartTime = Integer.valueOf(strStartTime[0]) * 100 + Integer.valueOf(strStartTime[1]);

            String[] strEndTime = autoTimeEnd.split(":");
            int intEndTime = Integer.valueOf(strEndTime[0]) * 100 + Integer.valueOf(strEndTime[1]);

            //logger.info("autoDistribute:intCurTime=" + intCurTime + ",intStartTime=" + intStartTime + "intEndTime=" + intEndTime);
            if (intCurTime < intStartTime || intCurTime > intEndTime) {
                logger.info("autoDistribute:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + ",不在可派单时间范围内，不自动派单:" + distributeArgsDRO.getAutoTimeStart() + "~" + distributeArgsDRO.getAutoTimeEnd());
                // 发送至定时自动派单队列
                boolean ret = this.sendWaitDistribute(orderWork, masterId, autoTimeStart, intCurTime, intEndTime, autoDistributeCount, OrderDistributeConsts.DISTRIBUTE_RULE_REASON_WORK_TIME);
                if (!ret) {
                    distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_WORK_TIME);
                }

                return false;
            }

        }

        // 分类型处理自动派单

        boolean res = false;

        switch (orderWork.getType()) {
            case OrderConsts.ORDER_TYPE_NEW: // 新单

                // 师傅加单：有指定派单工程师，先走指定自动派单
                if (masterId != null && masterId > 0) {

                    if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                        res = this.newOrderAutoDistribute2MasterTypeC(orderWork, orderDetail, masterId, distributeArgsDRO, autoDistributeCount, distributeSnapshotVO);
                    } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                        res = this.newOrderAutoDistribute2MasterTypeF(orderWork, orderDetail, masterId, distributeArgsDRO, autoDistributeCount, distributeSnapshotVO);
                    } else {
                        break;
                    }

                    // 如果指定工程师派单成功，结束
                    if (res) {
                        break;
                    }

                    // 保存师傅加单派单失败快照
                    long time = distributeSnapshotVO.getAutoDistributeTime().getTime() - 1;
                    //this.saveNonDistributeOrderLog(null, orderWork, new Date(time), "加单工程师不满足");

                    // 保存师傅加单派单失败快照
                    Date date = new Date(time);
                    // 不能自动派单有师傅列表
                    if (CollectionUtils.isNotEmpty(distributeSnapshotVO.getNonDistributeMasterList())) {
                        ZsOrderDistributeVO vo = distributeSnapshotVO.getNonDistributeMasterList().get(0);
                        distributeSnapshotVO.setDistributeFailReason(this.getMasterNonDistributeReason(vo));
                        // 保存日志
                        this.saveNonDistributeOrderLog(null, orderWork, date, distributeSnapshotVO.getDistributeFailReason());
                    } else {
                        this.saveNonDistributeOrderLog(null, orderWork, date, distributeSnapshotVO.getDistributeFailReason());
                    }

                }

                // 无指定派单工程师，或者指定工程师不符合条件，走普通自动派单
                if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                    res = this.newOrderAutoDistributeTypeC(orderWork, orderDetail, distributeArgsDRO, autoDistributeCount, distributeSnapshotVO);
                } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                    res = this.newOrderAutoDistributeTypeF(orderWork, orderDetail, distributeArgsDRO, autoDistributeCount, distributeSnapshotVO);
                }

                break;

            case OrderConsts.ORDER_TYPE_REWORK: // 返修单

                // 返修自动派单，不区分业务统一处理
                res = this.reworkOrderAutoDistribute(orderWork, orderDetail, distributeArgsDRO, autoDistributeCount, OrderDistributeConsts.DISTRIBUTE_WAY_SP, distributeSnapshotVO);

                // 如果源工程师派单成功，结束
                if (res) {
                    break;
                }

                // 保存源工程师派单失败快照
                long time = distributeSnapshotVO.getAutoDistributeTime().getTime() - 1;
                this.saveNonDistributeOrderLog(null, orderWork, new Date(time), distributeSnapshotVO.getDistributeFailReason());

                break;

            default:
                break;
        }

        return res;
    }

    // 新单自动派单 Type C
    private boolean newOrderAutoDistributeTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + "-新单自动派单");

        // 没有配置新单自动派单，结束
        if (distributeArgsDRO.getAutoStatusNew() == null
                || Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            return false;
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        do {
            // 指定工程师自动派
            if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_ENGINEER)) {
                logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",指定工程师自动派");
                distributeMaster = this.findQualifiedDistributeOrderMaster(orderWork, orderDetail);
                break;
            }

            // 初始化派单快照:规则无
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_NONE);

            DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);

            // 最大手头返修单：默认0
            int maxReworkCount = 0;

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            // 最大返修催单量：默认0
            int maxReworkReminderCount = 0;
            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }

            // 查询基础工程师列表
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
            List<ZsOrderDistributeVO> masterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

            // 没有基础工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_FIND);
                break;
            }

            // 初始化派单快照:不可派单列表
            distributeSnapshotVO.setNonDistributeMasterList(Lists.newArrayListWithCapacity(masterList.size()));

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            // 基础条件过滤，目前就是判断最大返修单量
            masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkCount,null, distributeSnapshotVO.getNonDistributeMasterList());

            // 基础条件过滤后，没有基础工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",基础条件过滤后，没有工程师就不处理了");
                break;
            }

            // 调用工程师服务查询app位置在线和服务范围状态
            this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

            // 非简单派单模式
            if (!Objects.equals(distributeArgsDRO.getNewSimpleStatus(), GlobalConsts.YES)) {

                // 检查非直营工程师是否在线
                masterList = this.onlineStatusSnapshotFilter(masterList, distributeSnapshotVO.getNonDistributeMasterList());

                // 过滤后没有工程师就不处理了
                if (CollectionUtils.isEmpty(masterList)) {
                    logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",非直营工程师是否在线过滤后没有工程师就不处理了");
                    break;
                }
            }

            // 只保留服务范围内的工程师
            masterList = this.scopeStatusSnapshotFilter(masterList, distributeSnapshotVO.getNonDistributeMasterList());

            // 服务范围过滤后没有工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",服务范围过滤后没有工程师就不处理了");
                break;
            }

            // 相似订单优先判断
            distributeMaster = this.getAutoDistributeSimilarMaster(masterList, distributeMasterQuery, distributeSnapshotVO);
            if (distributeMaster != null) {
                logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",相似订单");
                break;
            }

            // 计算距离
            this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

            // 数据准备工作，查询师傅统计信息并计算评分
            this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

            // 推荐条件过滤
            masterList = this.recommendSnapshotFilter(masterList, distributeMasterQuery, distributeSnapshotVO.getNonDistributeMasterList());

            if (CollectionUtils.isEmpty(masterList)) {
                logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",推荐条件过滤后没有工程师就不处理了");
                break;
            }

            // 获取自动派单师傅
            if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND)) {
                // 推荐派
                distributeMaster = this.getAutoDistributeScoreMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
            } else if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR)) {
                // 公平派
                distributeMaster = this.getAutoDistributeFairMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
            }

        } while (false);

        if (distributeMaster == null) {
            logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + ",新单自动派单：没有符合条件的工程师，结束");
            return false;
        }

        // 自动派单工程师保存到派单快照
        distributeSnapshotVO.setAutoDistributeMaster(distributeMaster);

        // 保存新单自动派单
        logger.info("newOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + "，新单自动派单成功：" + distributeMaster.getDistributeRuleText() + "，" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeMaster.getDistributeRuleText());
        distributeDTO.setDistributeRelateWorkText(distributeMaster.getDistributeRelateWorkText());
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(distributeMaster.getDistributeRule());
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        distributeDTO.setOperateTime(distributeSnapshotVO.getAutoDistributeTime());
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        boolean ret = this.saveAutoDistribute(distributeDTO);
        return ret;
    }

    // 新单自动派单 Type F
    private boolean newOrderAutoDistributeTypeF(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("newOrderAutoDistributeTypeF:workId=" + orderWork.getWorkId() + "-新单自动派单");

        // 没有配置新单自动派单，结束
        if (distributeArgsDRO.getAutoStatusNew() == null
                || Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)) {
            logger.info("newOrderAutoDistributeTypeF:workId=" + orderWork.getWorkId() + ",没有配置新单自动派单，结束");
            return false;
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        do {

            // F端订单，目前只支持指定工程师自动派
            if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_ENGINEER)) {
                logger.info("newOrderAutoDistributeTypeF:workId=" + orderWork.getWorkId() + ",指定工程师自动派");
                distributeMaster = this.findQualifiedDistributeOrderMaster(orderWork, orderDetail);
                break;
            }

        } while (false);

        if (distributeMaster == null) {
            logger.info("newOrderAutoDistributeTypeF:workId=" + orderWork.getWorkId() + ",新单自动派单：没有符合条件的工程师，结束");
            return false;
        }

        // 保存新单自动派单
        logger.info("newOrderAutoDistributeTypeF:workId=" + orderWork.getWorkId() + "，新单自动派单成功：" + distributeMaster.getDistributeRuleText() + "，" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeMaster.getDistributeRuleText());
        distributeDTO.setDistributeRelateWorkText(distributeMaster.getDistributeRelateWorkText());
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(distributeMaster.getDistributeRule());
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        distributeDTO.setOperateTime(null);
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        boolean ret = this.saveAutoDistribute(distributeDTO);
        return ret;
    }

    // 新单自动派单给指定工程师 Type C
    private boolean newOrderAutoDistribute2MasterTypeC(OrderWork orderWork, OrderDetail orderDetail, Integer masterId, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + "-新单自动派单给指定工程师:" + masterId);

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        do {
            // 只查询指定工程师
            DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
            distributeMasterQuery.setMatchMasterIdList(Lists.newArrayList(masterId));
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

            // 查询推荐工程师列表
            List<ZsOrderDistributeVO> recommendMasterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

            // 没有推荐工程师就不处理了
            if (CollectionUtils.isEmpty(recommendMasterList)) {
                logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，指定工程师不符合条件");

                // 没有工程师调用工程师接口查询不能服务原因
                EngineerSupportDistributeOrderDRO nonDistributeReason = this.checkNonDistributeReason(orderWork, orderDetail, masterId);
                if (Objects.isNull(nonDistributeReason)) {
                    logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，查询指定工程师不能服务原因失败");
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：查询加单工程师不能服务原因失败");
                    break;
                }
                if (Objects.equals(nonDistributeReason.getDistributeOrderStatus(), com.zmn.consts.GlobalConsts.NO)) {
                    logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                }
                break;
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(recommendMasterList, distributeMasterQuery);

            // 基础条件过滤，目前就是判断最大返修单量
            //recommendMasterList = this.baseDistributeFilter(recommendMasterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, null);
            distributeSnapshotVO.setNonDistributeMasterList(Lists.newArrayListWithCapacity(recommendMasterList.size()));
            recommendMasterList = this.baseDistributeSnapshotFilter(recommendMasterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, null, distributeSnapshotVO.getNonDistributeMasterList());

            // 基础条件过滤后，没有推荐工程师就不处理了
            if (CollectionUtils.isEmpty(recommendMasterList)) {
                logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，基础条件过滤后，指定工程师不符合条件");
                distributeSnapshotVO.setDistributeFailReason("加单工程师不满足");
                break;
            }

            distributeMaster = recommendMasterList.get(0);
        } while (false);

        if (distributeMaster == null) {
            return false;
        }

        // 保存新单自动派单
        logger.info("newOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，新单自动派单给指定工程师：" + distributeMaster.getMasterId());
        String distributeTypeText = "指定工程师自动派";
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText("指定工程师自动派");
        distributeDTO.setDistributeRelateWorkText(null);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SPECIAL_ENADD);
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        distributeDTO.setOperateTime(null);
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        this.saveAutoDistribute(distributeDTO);

        // 工程师加单特殊处理，永远返回true
        return true;
    }

    // 新单自动派单给指定工程师 Type F
    private boolean newOrderAutoDistribute2MasterTypeF(OrderWork orderWork, OrderDetail orderDetail, Integer masterId, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("newOrderAutoDistribute2MasterTypeF:workId=" + orderWork.getWorkId() + "-新单自动派单给指定工程师:" + masterId);

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        do {
            // 只查询指定工程师
            DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);
            distributeMasterQuery.setMatchMasterIdList(Lists.newArrayList(masterId));
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

            // 查询推荐工程师列表
            List<ZsOrderDistributeVO> recommendMasterList = this.listSpDistributeMasterByQuery(distributeMasterQuery);

            // 没有推荐工程师就不处理了
            if (CollectionUtils.isEmpty(recommendMasterList)) {
                logger.info("newOrderAutoDistribute2MasterTypeF:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，指定工程师不符合条件");

                // 没有工程师调用工程师接口查询不能服务原因
                EngineerSupportDistributeOrderDRO nonDistributeReason = this.checkNonDistributeReason(orderWork, orderDetail, masterId);
                if (Objects.isNull(nonDistributeReason)) {
                    logger.info("newOrderAutoDistribute2MasterTypeF:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，查询指定工程师不能服务原因失败");
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：查询加单工程师不能服务原因失败");
                    break;
                }
                if (Objects.equals(nonDistributeReason.getDistributeOrderStatus(), com.zmn.consts.GlobalConsts.NO)) {
                    logger.info("newOrderAutoDistribute2MasterTypeF:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                }
                break;
            }

            distributeMaster = recommendMasterList.get(0);
        } while (false);

        if (distributeMaster == null) {
            return false;
        }

        // 保存新单自动派单
        logger.info("newOrderAutoDistribute2MasterTypeF:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，新单自动派单给指定工程师：" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText("指定工程师自动派");
        distributeDTO.setDistributeRelateWorkText(null);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SPECIAL_ENADD);
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        distributeDTO.setOperateTime(null);
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        this.saveAutoDistribute(distributeDTO);

        // 工程师加单特殊处理，永远返回true
        return true;
    }

    /**
     * 平台直派-返修源工程师自动派
     */
    private boolean gridReworkOrderOriginalMasterAutoDistribute(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, int distributeWay, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        // 获取返修原单关联的所有返修单的主从工程师（含返修原单）相关信息 包含校验是否可派单
        List<ReworkOriginalEngineerBO> reworkOriginalOrderRelateMasterList = this.getReworkOriginalOrderRelateMasterList(orderWork, orderDetail);
        if (CollectionUtil.isNullOrEmpty(reworkOriginalOrderRelateMasterList)) {
            logger.info("工单[{}]-gridReworkOrderOriginalMasterAutoDistribute-查询不到返修原单相关的工程师!!!", orderWork.getWorkId());
            return Boolean.FALSE;
        }

        Set<Integer> engineerIdSet = reworkOriginalOrderRelateMasterList.stream().map(ReworkOriginalEngineerBO::getEngineerId).collect(Collectors.toSet());
        // 获取工程师基础信息
        Map<Integer, ForeignEngineerBasicInfoDRO> engineerInfoMap = this.getEngineerInfoMap(engineerIdSet);
        if (CollectionUtil.isNullOrEmpty(engineerInfoMap)) {
            logger.info("工单[{}]-gridReworkOrderOriginalMasterAutoDistribute-查询不到返修原单相关的工程师信息失败!!!", orderWork.getWorkId());
            return Boolean.FALSE;
        }
        // 获取派单总览指标
        Map<Integer, MasterOverviewIntegrateDRO> distributeOverviewInfoMap = this.getDistributeOverviewInfoMap(Lists.newArrayList(engineerIdSet), orderWork.getCityId(), orderWork.getOrderId(), orderWork.getDutyTime());
        // 返修催单限制
        int reworkReminderLimit = Optional.ofNullable(distributeArgsDRO.getReworkReminderLimit()).orElse(0);
        // 拆分可服务和不可服务列表
        List<ZsOrderDistributeVO> masterList = Lists.newArrayListWithCapacity(engineerIdSet.size());
        List<ZsOrderDistributeVO> nonDistributeMasterList = Lists.newArrayListWithCapacity(engineerIdSet.size());
        // 校验是否可服务
        EngineerSupportDistributeOrderQuery cannotDistributeOrderReasonQuery = new EngineerSupportDistributeOrderQuery();
        cannotDistributeOrderReasonQuery.setSerialNumber(UUID.randomUUID().toString());
        cannotDistributeOrderReasonQuery.setOriginalEngineerId(orderWork.getReworkMasterId());
        cannotDistributeOrderReasonQuery.setPlat(orderWork.getPlat());
        cannotDistributeOrderReasonQuery.setBizType(orderWork.getBizType());
        cannotDistributeOrderReasonQuery.setChannelId(orderWork.getChannelId());
        cannotDistributeOrderReasonQuery.setSubCompanyId(orderWork.getCompanyId());
        cannotDistributeOrderReasonQuery.setSpCompanyId(orderWork.getManageCompanyId());
        cannotDistributeOrderReasonQuery.setCityId(orderWork.getCityId());
        cannotDistributeOrderReasonQuery.setOrderLat(orderDetail.getLatitude());
        cannotDistributeOrderReasonQuery.setOrderLng(orderDetail.getLongitude());
        cannotDistributeOrderReasonQuery.setDutyTime(orderWork.getDutyTime());
        // PS:网格化差异点
        cannotDistributeOrderReasonQuery.setGridScreen(GlobalConsts.YES);
        // 后台技能
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(orderWork.getProductId(),
                orderWork.getShowProductId(), orderWork.getServCategId(), orderWork.getCategId());
        cannotDistributeOrderReasonQuery.setServSkillList(servSkillLists);
        // 后门开关永远开
        Integer backDoorStatus = GlobalConsts.YES;
        cannotDistributeOrderReasonQuery.setSkipServAreaCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setSkipOnlineCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setMaxProbationCycle(7);

        // 去重集合
       List<Integer> engineerIdList = Lists.newArrayList();
        // 返修优先排序
        this.sortReworkOriginalEngineerPriority(reworkOriginalOrderRelateMasterList);
        reworkOriginalOrderRelateMasterList.forEach(reworkOriginalEngineerBO -> {

            if (engineerIdList.contains(reworkOriginalEngineerBO.getEngineerId())) {
                return;
            }

            ForeignEngineerBasicInfoDRO engineerInfoDRO = engineerInfoMap.get(reworkOriginalEngineerBO.getEngineerId());
            MasterOverviewIntegrateDRO masterOverviewIntegrateDRO = distributeOverviewInfoMap.get(reworkOriginalEngineerBO.getEngineerId());

            boolean checkEngineerStatus = Boolean.TRUE;
            boolean checkEngineerSkill = Boolean.TRUE;
            boolean checkEngineerCity = Boolean.TRUE;

            cannotDistributeOrderReasonQuery.setEngineerId(reworkOriginalEngineerBO.getEngineerId());
            logger.info("检查师傅不能被派单原因入参:[{}]", JSON.toJSONString(cannotDistributeOrderReasonQuery));
            ResponseDTO<EngineerSupportDistributeOrderDRO> responseDTO = distributeOrderAssistListRemoteService.checkEngineerSupportDistributeOrder(cannotDistributeOrderReasonQuery);
            logger.info("检查师傅不能被派单原因出参:[{}]", JSON.toJSONString(responseDTO));
            EngineerSupportDistributeOrderDRO dro = responseDTO.getData();
            if (!responseDTO.isSuccess() || dro == null) {
                checkEngineerStatus = Boolean.FALSE;
                checkEngineerCity = Boolean.FALSE;
                checkEngineerSkill = Boolean.FALSE;
            }else if (Objects.nonNull(dro) && !Objects.equals(dro.getDistributeOrderStatus(), GlobalConsts.YES)){
                List<Integer> codes = dro.getNotDistributeOrderList().stream().map(NotSupportDistributeOrderEnum::getCode).collect(Collectors.toList());
                checkEngineerStatus = Collections.disjoint(codes, OrderDistributeConsts.ENGINEER_NON_DISTRIBUTE_REASON_STATUS);
                checkEngineerCity = Collections.disjoint(codes, OrderDistributeConsts.ENGINEER_NON_DISTRIBUTE_REASON_CITY);
                checkEngineerSkill = Collections.disjoint(codes, OrderDistributeConsts.ENGINEER_NON_DISTRIBUTE_REASON_SKILL);
            }

            ZsOrderDistributeVO vo = new ZsOrderDistributeVO();
            vo.setMasterId(reworkOriginalEngineerBO.getEngineerId());
            vo.setMasterName(engineerInfoDRO.getRealName());
            vo.setMasterPhone(engineerInfoDRO.getMobile());
            vo.setAgent(engineerInfoDRO.getCooperationType());
            vo.setHierarchyLevel(Optional.ofNullable(engineerInfoDRO.getHierarchyLevel()).orElse(0));
            vo.setOaStatus(engineerInfoDRO.getOaStatus());
            vo.setOrderEngineerType(reworkOriginalEngineerBO.getOrderEngineerType());
            vo.setPriorityType(reworkOriginalEngineerBO.getPriorityType());
            vo.setCheckEngineerStatus(checkEngineerStatus);
            vo.setCheckEngineerSkill(checkEngineerSkill);
            vo.setCheckServiceScope(checkEngineerCity);
            vo.setCheckMaxReworkReminderCount(Boolean.TRUE);
            if (reworkReminderLimit > 0 && Objects.nonNull(masterOverviewIntegrateDRO)) {
                vo.setReworkReminderCount(Optional.ofNullable(masterOverviewIntegrateDRO.getReworkReminderCount()).orElse(0));
                vo.setCheckMaxReworkReminderCount(reworkReminderLimit > vo.getReworkReminderCount());
            }

            if (checkEngineerStatus && checkEngineerCity && checkEngineerSkill && vo.getCheckMaxReworkReminderCount()) {
                masterList.add(vo);
            }else {
                nonDistributeMasterList.add(vo);
            }

            engineerIdList.add(reworkOriginalEngineerBO.getEngineerId());
        });


        if (CollectionUtil.isNullOrEmpty(masterList)) {
            logger.info("工单[{}]-gridReworkOrderOriginalMasterAutoDistribute-源工程师均不可服务!!!", orderWork.getWorkId());
            return Boolean.FALSE;
        }

        // 获取自动派单工程师
        ReworkOriginalEngineerBO reworkEngineer = reworkOriginalOrderRelateMasterList.get(0);
        ZsOrderDistributeVO reworkMaster = masterList.get(0);
        // 增加七天内外描述
        String distributeRuleName = OrderDistributeConsts.getDistributeRuleName(OrderDistributeConsts.DISTRIBUTE_RULE_REWORK_PRIORITY);
        if (Objects.equals(reworkEngineer.getInSevenDays(), GlobalConsts.YES)) {
            distributeRuleName += "(七天内)";
        }else {
            distributeRuleName += "(七天外)";
        }
        // 派单快照参数设置
        masterList.remove(0);
        reworkMaster.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REWORK_PRIORITY);
        distributeSnapshotVO.setAutoDistributeMaster(reworkMaster);
        distributeSnapshotVO.setMasterList(masterList);
        distributeSnapshotVO.setNonDistributeMasterList(nonDistributeMasterList);
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REWORK_PRIORITY);
        distributeSnapshotVO.setDistributeRuleName(distributeRuleName);

        reworkMaster.setDistributeRuleText(distributeRuleName);
        // 保存返修单自动派单
        logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，返修自动派单：" + reworkMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setAutoDistribute(Boolean.TRUE);
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(reworkMaster.getMasterId());
        distributeDTO.setMasterName(reworkMaster.getMasterName());
        distributeDTO.setMasterPhone(reworkMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeRuleName);
        distributeDTO.setDistributeRelateWorkText(null);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REWORK_PRIORITY);
        // 派单路径
        distributeDTO.setDistributeWay(distributeWay);
        distributeDTO.setOperateTime(distributeSnapshotVO.getAutoDistributeTime());
        // 工作网格类型
        distributeDTO.setWorkspaceType(reworkMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(reworkMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(reworkMaster.getDistributeGrid());
        this.saveAutoDistribute(distributeDTO);

        return Boolean.TRUE;
    }

    // 返修单自动派单
    private boolean reworkOrderAutoDistribute(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO, Integer autoDistributeCount, int distributeWay, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "-返修单自动派单");

        // 没有配置返修单自动派单，结束
        if (!Objects.equals(distributeArgsDRO.getAutoStatusRework(), GlobalConsts.YES)) {
            logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，没有配置返修单自动派单，结束");
            distributeSnapshotVO.setDistributeFailReason("源工程师不满足，原因：没有配置返修单自动派单");
            return false;
        }

        // 返修原工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        if (reworkMasterId == null || reworkMasterId == 0) {
            logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，没有返修原工程师，结束");
            distributeSnapshotVO.setDistributeFailReason("源工程师不满足，原因：没有返修原工程师");
            return false;
        }

        // 查询原工程师
        ZsOrderDistributeVO reworkMaster = this.findDistributeOrderByOriginalMaster(orderWork, reworkMasterId, false);

        // 返修原工程师不符合派单条件，结束
        if (reworkMaster == null) {
            logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，返修原工程师不符合派单条件");

            // 返修工程师不符合条件需要重新调接口判断不能服务原因
            EngineerSupportDistributeOrderDRO nonDistributeReason = this.checkNonDistributeReason(orderWork, orderDetail, reworkMasterId);
            if (Objects.isNull(nonDistributeReason)) {
                logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，查询返修原工程师不能服务原因失败，结束");
                distributeSnapshotVO.setDistributeFailReason("源工程师不满足，原因：查询返修原工程师不能服务原因失败");
                return false;
            }
            if (Objects.equals(nonDistributeReason.getDistributeOrderStatus(), com.zmn.consts.GlobalConsts.NO)) {
                logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，" + nonDistributeReason.getNotDistributeOrderEnum().getName() + "，结束");
                distributeSnapshotVO.setDistributeFailReason("源工程师不满足，原因：" + nonDistributeReason.getNotDistributeOrderEnum().getName());
            }
            return false;
        }

        // 保存返修单自动派单
        logger.info("reworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，返修自动派单：" + reworkMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(reworkMaster.getMasterId());
        distributeDTO.setMasterName(reworkMaster.getMasterName());
        distributeDTO.setMasterPhone(reworkMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText("返修源工程师自动派");
        distributeDTO.setDistributeRelateWorkText(null);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REWORK);
        // 派单路径
        distributeDTO.setDistributeWay(distributeWay);
        distributeDTO.setOperateTime(null);
        // 工作网格类型
        distributeDTO.setWorkspaceType(reworkMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(reworkMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(reworkMaster.getDistributeGrid());
        this.saveAutoDistribute(distributeDTO);

        return true;
    }

    //以下为内部处理方法//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //查询统计信息部分开始******************************************************************************************************//


    /**
     * 获取返修原单相关工程师列表
     *
     * @param orderWork
     * @return
     */
    private List<ReworkOriginalEngineerBO> getReworkOriginalOrderRelateMasterList(OrderWork orderWork, OrderDetail orderDetail) {

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.filter(QueryBuilders.multiMatchQuery(orderWork.getOriginalId(), "orderId", "originalId"));
        queryBuilder.filter(QueryBuilders.existsQuery("completeTime"));
        queryBuilder.filter(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));
        NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder);
        SourceFilter sourceFilter = new FetchSourceFilterBuilder()
                .withIncludes("orderId", "workId", "completeTime", "masterList")
                .build();
        nativeSearchQuery.addSourceFilter(sourceFilter);
        List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(nativeSearchQuery);

        if (CollectionUtil.isNullOrEmpty(esOrderWorks)) {
            return Collections.emptyList();
        }

        // 获取完成时间最新的工单信息
        EsOrderWork lastOrder = esOrderWorks.stream().max(Comparator.comparing(EsOrderWork::getCompleteTime)).get();
        // 判断是否返修完成7天内
        boolean isSevenDays = System.currentTimeMillis() - lastOrder.getCompleteTime().getTime() < 7 * 24 * 60 * 60 * 1000;
        // 获取最优先订单id
        Long firstPriorityOrderId = isSevenDays ? lastOrder.getOrderId() : orderWork.getOriginalId();

        List<ReworkOriginalEngineerBO> reworkOriginalEngineerBOList = new ArrayList<>();
        esOrderWorks.forEach(esOrderWork -> {
            List<EsOrderWorkMaster> esOrderWorkMasterList = esOrderWork.getMasterList();
            if (CollectionUtil.isNotNullOrEmpty(esOrderWorkMasterList)) {
                int firstPriority = esOrderWork.getOrderId().equals(firstPriorityOrderId) ? GlobalConsts.YES : GlobalConsts.NO;
                List<ReworkOriginalEngineerBO> reworkOriginalEngineerBOS = esOrderWorkMasterList.stream().map(esOrderWorkMaster -> {
                    ReworkOriginalEngineerBO reworkOriginalEngineerBO = new ReworkOriginalEngineerBO();
                    reworkOriginalEngineerBO.setEngineerId(esOrderWorkMaster.getMasterId());
                    reworkOriginalEngineerBO.setOrderEngineerType(esOrderWorkMaster.getMasterType());
                    reworkOriginalEngineerBO.setCompleteTime(esOrderWork.getCompleteTime());
                    reworkOriginalEngineerBO.setFirstPriority(firstPriority);
                    reworkOriginalEngineerBO.setInSevenDays(isSevenDays ? GlobalConsts.YES : GlobalConsts.NO);
                    reworkOriginalEngineerBO.setPriorityType(GlobalConsts.NONE);
                    if (esOrderWork.getOrderId().equals(orderWork.getOriginalId()) && NumberUtil.isNullOrZero(reworkOriginalEngineerBO.getPriorityType())) {
                        reworkOriginalEngineerBO.setPriorityType(GlobalConsts.NO);
                    } else if (isSevenDays && esOrderWork.getOrderId().equals(lastOrder.getOrderId())) {
                        reworkOriginalEngineerBO.setPriorityType(GlobalConsts.YES);
                    }
                    return reworkOriginalEngineerBO;
                }).collect(Collectors.toList());
                reworkOriginalEngineerBOList.addAll(reworkOriginalEngineerBOS);
            }
        });
        return reworkOriginalEngineerBOList;
    }
    // 查找指定派单工程师
    private ZsOrderDistributeVO findQualifiedDistributeOrderMaster(OrderWork orderWork, OrderDetail orderDetail) {
        ZsOrderDistributeVO qualifiedMaster = null;

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, false);

        EngineerAutomaticDistributeOrderQuery qualifiedDistributeOrderQuery = new EngineerAutomaticDistributeOrderQuery();

        qualifiedDistributeOrderQuery.setSerialNumber(UUID.randomUUID().toString());

        qualifiedDistributeOrderQuery.setPlat(distributeMasterQuery.getPlat());
        qualifiedDistributeOrderQuery.setBizType(distributeMasterQuery.getBizType());
        qualifiedDistributeOrderQuery.setChannelId(distributeMasterQuery.getChannelId());
        qualifiedDistributeOrderQuery.setSubCompanyId(distributeMasterQuery.getCompanyId());
        qualifiedDistributeOrderQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
        qualifiedDistributeOrderQuery.setCityId(distributeMasterQuery.getCityId());
        qualifiedDistributeOrderQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        qualifiedDistributeOrderQuery.setServCategId(distributeMasterQuery.getServCategId());
        qualifiedDistributeOrderQuery.setCategId(distributeMasterQuery.getShowCategId());
        qualifiedDistributeOrderQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());

        // 后台技能
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
        qualifiedDistributeOrderQuery.setServSkillList(servSkillLists);

        //logger.info("getQualifiedDistributeOrderEngineer:" + qualifiedDistributeOrderQuery);
        // todo fubiao
        logger.info("findQualifiedDistributeOrderMaster#getForAutomaticDistributeOrder 入参 [{}]",JSON.toJSONString(qualifiedDistributeOrderQuery));
        ResponseDTO<EngineerDistributeOrderDRO> responseDTO = spDistributeOrderListRemoteService.getForAutomaticDistributeOrder(qualifiedDistributeOrderQuery);
        logger.info("findQualifiedDistributeOrderMaster#getForAutomaticDistributeOrder 出参 [{}]",JSON.toJSONString(responseDTO));
        //logger.info("getQualifiedDistributeOrderEngineer responseDTO:" + responseDTO);

        if (responseDTO.isSuccess() && responseDTO.getData() != null) {
            qualifiedMaster = this.transformDistributeObjectDRO2VO(responseDTO.getData());
            // 设置派单规则为：指定工程师派单
            qualifiedMaster.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SPECIAL_APPOINT);
        }

        return qualifiedMaster;
    }

    /**
     * 保存自动派单
     *
     * @param distributeDTO
     */
    private boolean saveAutoDistribute(OrderDistributeDTO distributeDTO) throws OmsBaseException {

        // 标识是自动派单
        distributeDTO.setAutoDistribute(true);

        // 设置成已派单
        distributeDTO.setStatus(OrderStatusConsts.WORK_STATUS_DISTRIBUTE);
        distributeDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        distributeDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        distributeDTO.setOperator("系统");
        return zsCustomWorkBService.saveDistribute(distributeDTO);
    }

    // 获取已派相似订单师傅列表
    private List<ZsOrderDistributeVO> getDistributeSimilarOrderMasterList(List<ZsOrderDistributeVO> waitProcessList, DistributeMasterQuery distributeMasterQuery, boolean remove) {

        // 查询相似订单的师傅
        List<Integer> similarOrderMasterIds = this.getDistributedSimilarOrderMasterId(waitProcessList, distributeMasterQuery);

        // 没有返回空
        if (CollectionUtils.isEmpty(similarOrderMasterIds)) {
            logger.info("distributeSimilarOrderMasterList:null");
            return null;
        }

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = Lists.newArrayListWithCapacity(similarOrderMasterIds.size());
        Set<Integer> idSet = new HashSet<>(similarOrderMasterIds);

        Iterator<ZsOrderDistributeVO> it = waitProcessList.iterator();

        while (it.hasNext()) {
            ZsOrderDistributeVO vo = it.next();

            // 把相似订单的师傅移动到相似订单师傅列表
            if (idSet.contains(vo.getMasterId())) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SIMILAR);
                vo.setDistributeRuleTitle("相似");
                vo.setDistributeRuleText("已派单相似");
                distributeSimilarOrderMasterList.add(vo);

                if (remove) {
                    it.remove();
                }
            }
        }

        // 排序
        this.sortMasterListBySimilarRule(distributeSimilarOrderMasterList);

        logger.info("distributeSimilarOrderMasterList:" + distributeSimilarOrderMasterList);
        return distributeSimilarOrderMasterList;
    }

    // 获取未派相似订单师傅列表
    private List<ZsOrderDistributeVO> getUnDistributeSimilarOrderMasterList(List<EsOrderWork> esOrderWorks, List<ZsOrderDistributeVO> waitProcessList, DistributeMasterQuery distributeMasterQuery, boolean remove) {

        // 没有返回空
        if (CollectionUtils.isEmpty(esOrderWorks)) {
            logger.info("没有未派相似订单");
            return null;
        }

        // 查询满足全部订单技能条件的师傅
        DistributeMasterQuery similarOrderSkillQuery = new DistributeMasterQuery();
        similarOrderSkillQuery.setPlat(distributeMasterQuery.getPlat());
        similarOrderSkillQuery.setBizType(distributeMasterQuery.getBizType());
        similarOrderSkillQuery.setBackdoorStatus(GlobalConsts.YES);
        similarOrderSkillQuery.setServCategId(distributeMasterQuery.getServCategId());
        similarOrderSkillQuery.setShowCategId(distributeMasterQuery.getShowCategId());
        similarOrderSkillQuery.setProductId(distributeMasterQuery.getProductId());
        similarOrderSkillQuery.setShowProductId(distributeMasterQuery.getShowProductId());
        similarOrderSkillQuery.setCategId(distributeMasterQuery.getCategId());
        similarOrderSkillQuery.setGridDistribute(distributeMasterQuery.isGridDistribute());
        similarOrderSkillQuery.setServProductGroupId(distributeMasterQuery.getServProductGroupId());
        similarOrderSkillQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        // 查询出来的师傅必须包含在待处理列表内
        List<Integer> waitProcessMasterIds = waitProcessList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
        similarOrderSkillQuery.setMatchMasterIdList(waitProcessMasterIds);

        //  所需技能列表
        List<List<DistributeOrderSkillQuery>> skillLists = new ArrayList<>();
        List<DistributeOrderSkillQuery> skillList;

        // 当前单技能
        skillList = this.buildSkillList(similarOrderSkillQuery.getProductId(), similarOrderSkillQuery.getShowProductId(), similarOrderSkillQuery.getServCategId(), similarOrderSkillQuery.getCategId());
        skillLists.add(skillList);

        // 未派相似单技能
        for (EsOrderWork esOrderWork : esOrderWorks) {
            skillList = this.buildSkillList(esOrderWork.getProductId(), esOrderWork.getShowProductId(), esOrderWork.getServCategId(), esOrderWork.getCategTwoId());
            skillLists.add(skillList);
        }

        // 调用engineer dubbo查询满足多个工单技能的师傅
        List<ZsOrderDistributeVO> multiOrderSkillMasterList = this.listSpDistributeMasterByQuery(similarOrderSkillQuery, skillLists);

        if (CollectionUtils.isEmpty(multiOrderSkillMasterList)) {
            logger.info("没有符合未派相似订单条件的师傅");
            return null;
        }

        // 未派相似订单师傅列表
        List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = Lists.newArrayListWithCapacity(multiOrderSkillMasterList.size());

        // 提取结果集中的师傅id
        Set<Integer> idSet = multiOrderSkillMasterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toSet());
        Iterator<ZsOrderDistributeVO> it = waitProcessList.iterator();

        while (it.hasNext()) {
            ZsOrderDistributeVO vo = it.next();

            // 把相似订单的师傅移动到相似订单师傅列表
            if (idSet.contains(vo.getMasterId())) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_MULTI);
                vo.setDistributeRuleTitle("多");
                vo.setDistributeRuleText("未派单相似");
                unDistributeSimilarOrderMasterList.add(vo);

                if (remove) {
                    it.remove();
                }
            }
        }

        // 排序
        this.sortMasterListBySimilarRule(unDistributeSimilarOrderMasterList);

        logger.info("unDistributeSimilarOrderMasterList:" + unDistributeSimilarOrderMasterList);
        return unDistributeSimilarOrderMasterList;
    }

    // 获取首轮师傅列表
    private List<ZsOrderDistributeVO> getFirstOrderMasterList(List<ZsOrderDistributeVO> waitProcessList, boolean remove) {

        // 首轮师傅列表
        List<ZsOrderDistributeVO> firstOrderMasterList = Lists.newArrayListWithCapacity(waitProcessList.size());

        // 把今日新单为0同时要满足服务范围&主技能&最大手头单的师傅放到首轮师傅列表，并从待处理列表移除
        Iterator<ZsOrderDistributeVO> it = waitProcessList.iterator();

        while (it.hasNext()) {
            ZsOrderDistributeVO vo = it.next();

            // 今日新单派单量=0
            if (vo.getDistributeNewCount() == 0) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                vo.setDistributeRuleTitle("首");
                vo.setDistributeRuleText("首轮优先");
                firstOrderMasterList.add(vo);

                if (remove) {
                    it.remove();
                }
            }
        }

        // 进行新手优先处理
        if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
            firstOrderMasterList = this.noviceFirstMasterList(firstOrderMasterList);
        }

        return firstOrderMasterList;
    }

    /**
     * 获取自动派单首轮工程师列表
     */
    private List<ZsOrderDistributeVO> getAutoFirstOrderMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 首轮师傅列表
        List<ZsOrderDistributeVO> firstOrderMasterList = Lists.newArrayListWithCapacity(masterList.size());

        // 把今日新单为0同时要满足服务范围&主技能&最大手头单的师傅放到首轮师傅列表

        for (ZsOrderDistributeVO vo : masterList) {

            // 今日新单派单量=0
            if (vo.getDistributeNewCount() == 0) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                vo.setDistributeRuleTitle("首");
                vo.setDistributeRuleText("首轮优先");
                firstOrderMasterList.add(vo);
            }
        }

        // 没有返回null
        if (CollectionUtils.isEmpty(firstOrderMasterList)) {
            return null;
        }

        // 进行新手优先处理
        firstOrderMasterList = this.noviceFirstMasterList(firstOrderMasterList);

        // 如果是录单预派，直接返回
        if (distributeMasterQuery.isPreDistribute()) {
            return firstOrderMasterList;
        }

        // 自动派单处理首轮并发问题
        List<ZsOrderDistributeVO> resultList = Lists.newArrayListWithCapacity(firstOrderMasterList.size());

        boolean ret = false;
        for (ZsOrderDistributeVO vo : firstOrderMasterList) {
            String redisKey = String.format(RedisKeyConsts.AUTO_DISTRIBUTE_FIRST_MASTER_KEY, vo.getMasterId());

            if (!ret) {
                // 将选定首轮工程师id保存到redis里面的首轮工程师id集合，锁定10秒
                ret = redisTemplate.opsForValue().setIfAbsent(redisKey, "1", 10, TimeUnit.SECONDS);
            }

            if (ret) {
                resultList.add(vo);
            }
        }

        return resultList;
    }

    /**
     * 获取自动派单首轮工程师列表
     */
    private List<ZsOrderDistributeVO> gridGetAutoFirstOrderMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {

        // 首轮保护只针对主网格 workspaceType 和 主技能 增加保护等级判断
        List<ZsOrderDistributeVO> waitProcessList =  masterList.stream()
                .filter(vo -> Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN))
                .filter(vo -> Objects.equals(vo.getMainSkillId(), distributeMasterQuery.getMainSkillId()))
                .filter(vo -> (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getProtectionFirstProductGroupMap())
                        || vo.getHierarchyLevel() >= distributeArgsDRO.getProtectionFirstProductGroupMap().getOrDefault(vo.getProductGroupId(), 0)))
                .collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(waitProcessList)) {
            return null;
        }

        // 首轮师傅列表
        List<ZsOrderDistributeVO> firstOrderMasterList = Lists.newArrayListWithCapacity(waitProcessList.size());

        // 把今日新单为0同时要满足服务范围&主技能&最大手头单的师傅放到首轮师傅列表

        for (ZsOrderDistributeVO vo : waitProcessList) {

            // 今日新单派单量+改派轮次值=0
            if (vo.getDistributeNewCount() + vo.getRedistributeCount() == 0) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                vo.setDistributeRuleTitle("首");
                vo.setDistributeRuleText("首轮优先");
                firstOrderMasterList.add(vo);
            }
        }

        // 没有返回null
        if (CollectionUtil.isNullOrEmpty(firstOrderMasterList)) {
            return null;
        }

        // 进行新手优先处理
//        firstOrderMasterList = this.noviceFirstMasterList(firstOrderMasterList);

        /** 这里不在调用原有新手优先逻辑 直接排序 原排序中新增新手相关排序**/
        // 首轮排序
        this.sortMasterListByYesterdayDistributeCount(firstOrderMasterList);

        // 如果是录单预派，直接返回
        if (distributeMasterQuery.isPreDistribute()) {
            return firstOrderMasterList;
        }

        // 自动派单处理首轮并发问题
        List<ZsOrderDistributeVO> resultList = Lists.newArrayListWithCapacity(firstOrderMasterList.size());

        boolean ret = false;
        for (ZsOrderDistributeVO vo : firstOrderMasterList) {
            String redisKey = String.format(RedisKeyConsts.AUTO_DISTRIBUTE_FIRST_MASTER_KEY, vo.getMasterId());

            if (!ret) {
                // 将选定首轮工程师id保存到redis里面的首轮工程师id集合，锁定10秒
                ret = redisTemplate.opsForValue().setIfAbsent(redisKey, "1", 10, TimeUnit.SECONDS);
            }

            if (ret) {
                resultList.add(vo);
            }
        }

        return resultList;
    }

    /**
     * 获取自动派单多轮保护工程师列表-平台直派
     */
    private List<ZsOrderDistributeVO> gridGetAutoManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {

        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return null;
        }

        if (Objects.isNull(distributeArgsDRO)) {
            return null;
        }

        //  查询工程师工作时长
        this.getMasterListWorkingTimes(masterList);

        // 判断是否多轮优先保护
        if (Objects.equals(distributeArgsDRO.getPriorityProtectionStatus(), GlobalConsts.YES)) {
            List<ZsOrderDistributeVO> priorityManyProtectionMasterList = this.gridGetAutoPriorityManyProtectionMasterList(masterList, distributeArgsDRO);
            if (CollectionUtil.isNotNullOrEmpty(priorityManyProtectionMasterList)) {
                return priorityManyProtectionMasterList;
            }
        }

        // 没有多轮优先 走普通多轮保护
        return gridGetAutoOrdinaryManyProtectionMasterList(masterList, distributeArgsDRO);
    }

    /**
     * 获取自动派单优先多轮保护工程师列表-平台直派
     */
    private List<ZsOrderDistributeVO> gridGetAutoPriorityManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {

        if (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getPriorityProtectionGroupTimes())
                && CollectionUtil.isNullOrEmpty(distributeArgsDRO.getPriorityProtectionTimesProductGroupMap())) {
            return null;
        }

        // 过滤出优质工程师列表 filter excellentFlag
       /* List<ZsOrderDistributeVO> excellentMasterList = this.excellentDistributeFilter(masterList);
        if (CollectionUtil.isNullOrEmpty(excellentMasterList)) {
            // 没有优质工程师 返回空
            return null;
        }*/



        // 多轮优先保护师傅列表
        List<ZsOrderDistributeVO> priorityManyProtectionMasterList = Lists.newArrayListWithCapacity(masterList.size());

        masterList.stream().filter(vo -> NumberUtil.isNotNullOrZero(vo.getProductGroupId())).forEach(vo -> {
            // 找到工程师产品组（分级）对应的设置
            Integer setupProtectionDefaultTimes = distributeArgsDRO.getPriorityProtectionRoundsByProductGroupIdAndHierarchyLevel(vo.getProductGroupId(), vo.getHierarchyLevel());

            if (NumberUtil.isNullOrZero(setupProtectionDefaultTimes) || NumberUtil.isNullOrZero(vo.getWorkingHours()) || NumberUtil.isNullOrZero(vo.getScheduleHours())) {
                return;
            }

            // 折算保护轮次
            int protectionDefaultTimes = (int) ((double) vo.getWorkingHours() / (double) vo.getScheduleHours() * (double) setupProtectionDefaultTimes);
            // 判断是否首轮准入
            int firstRounds = 0;
            if (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getProtectionFirstProductGroupMap())
                    || vo.getHierarchyLevel() >= distributeArgsDRO.getProtectionFirstProductGroupMap().getOrDefault(vo.getProductGroupId(), 0)){
                firstRounds = 1;
            }
            // 把今日新单+改派轮次值小于保护轮次的师傅放到保护列表
            int roundValue = vo.getDistributeNewCount() + vo.getRedistributeCount() < firstRounds ? 0 : vo.getDistributeNewCount() + vo.getRedistributeCount() - firstRounds;
            if (roundValue < protectionDefaultTimes) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_PROTECTION_PRIORITY);
                vo.setDistributeRuleTitle("保");
                vo.setDistributeRuleText(String.format("多轮优先保护%d-%d", roundValue + 1, protectionDefaultTimes));
                priorityManyProtectionMasterList.add(vo);
            }
        });

        // 没有返回null
        if (CollectionUtils.isEmpty(priorityManyProtectionMasterList)) {
            return null;
        }

        // 多轮保护排序
        this.sortMasterListByManyProtection(priorityManyProtectionMasterList);

        return priorityManyProtectionMasterList;
    }

    /**
     * 获取自动派单普通多轮保护工程师列表-平台直派
     */
    private List<ZsOrderDistributeVO> gridGetAutoOrdinaryManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {

        if (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getProtectionGroupTimes())
                && CollectionUtil.isNullOrEmpty(distributeArgsDRO.getProtectionTimesNormalProductGroupMap())) {
            return null;
        }

        // 多轮保护师傅列表
        List<ZsOrderDistributeVO> manyProtectionMasterList = Lists.newArrayListWithCapacity(masterList.size());

        // 计算保护轮次
        masterList.stream().filter(vo -> NumberUtil.isNotNullOrZero(vo.getProductGroupId())).forEach(vo -> {
            // 找到工程师产品组对应的设置
            Integer setupProtectionDefaultTimes = distributeArgsDRO.getProtectionRoundsByProductGroupIdAndHierarchyLevel(vo.getProductGroupId(), vo.getHierarchyLevel());

            if (NumberUtil.isNullOrZero(setupProtectionDefaultTimes) || NumberUtil.isNullOrZero(vo.getWorkingHours()) || NumberUtil.isNullOrZero(vo.getScheduleHours())) {
                return;
            }

            // 折算保护轮次
            int protectionDefaultTimes = (int)((double)vo.getWorkingHours() / (double)vo.getScheduleHours() * (double)setupProtectionDefaultTimes);

            // 判断是否首轮准入
            int firstRounds = 0;
            if (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getProtectionFirstProductGroupMap())
                    || vo.getHierarchyLevel() >= distributeArgsDRO.getProtectionFirstProductGroupMap().getOrDefault(vo.getProductGroupId(), 0)){
                firstRounds = 1;
            }
            // 把今日新单+改派轮次值小于保护轮次的师傅放到保护列表
            int roundValue = vo.getDistributeNewCount() + vo.getRedistributeCount() < firstRounds ? 0 : vo.getDistributeNewCount() + vo.getRedistributeCount() - firstRounds;
            if (Objects.equals(distributeArgsDRO.getPriorityProtectionStatus(), GlobalConsts.YES)) {
                // 如果存在多轮优先配置轮次 多轮普通需去除多轮优先保护轮次
                Integer setupPriorityProtectionDefaultTimes = distributeArgsDRO.getPriorityProtectionRoundsByProductGroupIdAndHierarchyLevel(vo.getProductGroupId(), vo.getHierarchyLevel());
                if (NumberUtil.isNotNullOrZero(setupPriorityProtectionDefaultTimes)) {
                    roundValue = setupPriorityProtectionDefaultTimes > roundValue ? 0 : roundValue - setupPriorityProtectionDefaultTimes;
                }
            }
            if (roundValue < protectionDefaultTimes) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_PROTECTION_ORDINARY);
                vo.setDistributeRuleTitle("保");
                vo.setDistributeRuleText(String.format("多轮保护%d-%d", roundValue + 1, protectionDefaultTimes));
                manyProtectionMasterList.add(vo);
            }
        });

        // 没有返回null
        if (CollectionUtils.isEmpty(manyProtectionMasterList)) {
            return null;
        }

        // 多轮保护排序
        this.sortMasterListByManyProtection(manyProtectionMasterList);

        return manyProtectionMasterList;
    }

    /**
     * 获取自动派单多轮保护工程师列表
     */
    private List<ZsOrderDistributeVO> getAutoManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {
        // 判断是否多轮优先保护
        if (Objects.equals(distributeArgsDRO.getPriorityProtectionStatus(), GlobalConsts.YES)) {
            List<ZsOrderDistributeVO> priorityManyProtectionMasterList = this.getAutoPriorityManyProtectionMasterList(masterList, distributeArgsDRO);
            if (CollectionUtil.isNotNullOrEmpty(priorityManyProtectionMasterList)) {
                return priorityManyProtectionMasterList;
            }
        }

        // 没有多轮优先 走普通多轮保护
        return getAutoOrdinaryManyProtectionMasterList(masterList, distributeArgsDRO);
    }

    /**
     * 获取自动派单优先多轮保护工程师列表
     */
    private List<ZsOrderDistributeVO> getAutoPriorityManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {
        if (distributeArgsDRO == null || distributeArgsDRO.getProtectionGroupTimes() == null) {
            return null;
        }

        // 过滤出优质工程师列表 filter excellentFlag
        List<ZsOrderDistributeVO> excellentMasterList = this.excellentDistributeFilter(masterList);
        if (CollectionUtil.isNullOrEmpty(excellentMasterList)) {
            // 没有优质工程师 返回空
            return null;
        }

        //  查询工程师工作时长
        this.getMasterListWorkingTimes(excellentMasterList);

        // 多轮优先保护师傅列表
        List<ZsOrderDistributeVO> priorityManyProtectionMasterList = Lists.newArrayListWithCapacity(excellentMasterList.size());

        Map<String, Integer> mapProtectionGroupTimes = distributeArgsDRO.getPriorityProtectionGroupTimes();

        for (ZsOrderDistributeVO vo : excellentMasterList) {

            if (vo.getProductGroupId() == null) {
                continue;
            }

            // 找到工程师产品组对应的设置
            Integer setupProtectionDefaultTimes = mapProtectionGroupTimes.get(String.valueOf(vo.getProductGroupId()));

            if (setupProtectionDefaultTimes == null || setupProtectionDefaultTimes == 0 || vo.getWorkingHours() == null || vo.getWorkingHours() == 0 || vo.getScheduleHours() == null || vo.getScheduleHours() == 0) {
                continue;
            }

            // 折算保护轮次
            int protectionDefaultTimes = (int)((double)vo.getWorkingHours() / (double)vo.getScheduleHours() * (double)setupProtectionDefaultTimes);

            // 把今日新单小于保护轮次的师傅放到保护列表
            if (vo.getDistributeNewCount() < protectionDefaultTimes) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_PROTECTION_PRIORITY);
                vo.setDistributeRuleTitle("保");
                vo.setDistributeRuleText(String.format("多轮优先保护%d-%d", vo.getDistributeNewCount() + 1, protectionDefaultTimes));
                priorityManyProtectionMasterList.add(vo);
            }
        }

        // 没有返回null
        if (CollectionUtils.isEmpty(priorityManyProtectionMasterList)) {
            return null;
        }

        // 多轮保护排序
        this.sortMasterListByManyProtection(priorityManyProtectionMasterList);

        return priorityManyProtectionMasterList;
    }

    /**
     * 过滤优质工程师
     * @param masterList
     * @return
     */
    private List<ZsOrderDistributeVO> excellentDistributeFilter(List<ZsOrderDistributeVO> masterList) {
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return null;
        }
        return masterList.stream().filter(master -> Objects.equals(master.getExcellentFlag(), GlobalConsts.YES)).collect(Collectors.toList());
    }

    /**
     * 获取自动派单普通多轮保护工程师列表
     */
    private List<ZsOrderDistributeVO> getAutoOrdinaryManyProtectionMasterList(List<ZsOrderDistributeVO> masterList, DistributeArgsDRO distributeArgsDRO) {
        if (distributeArgsDRO == null || distributeArgsDRO.getProtectionGroupTimes() == null) {
            return null;
        }

        //  查询工程师工作时长
        this.getMasterListWorkingTimes(masterList);

        // 多轮保护师傅列表
        List<ZsOrderDistributeVO> manyProtectionMasterList = Lists.newArrayListWithCapacity(masterList.size());

        Map<String, Integer> mapProtectionGroupTimes = distributeArgsDRO.getProtectionGroupTimes();

        for (ZsOrderDistributeVO vo : masterList) {

            if (vo.getProductGroupId() == null) {
                continue;
            }

            // 找到工程师产品组对应的设置
            Integer setupProtectionDefaultTimes = mapProtectionGroupTimes.get(String.valueOf(vo.getProductGroupId()));

            if (setupProtectionDefaultTimes == null || setupProtectionDefaultTimes == 0 || vo.getWorkingHours() == null || vo.getWorkingHours() == 0 || vo.getScheduleHours() == null || vo.getScheduleHours() == 0) {
                continue;
            }

            // 折算保护轮次
            int protectionDefaultTimes = (int)((double)vo.getWorkingHours() / (double)vo.getScheduleHours() * (double)setupProtectionDefaultTimes);

            // 把今日新单小于保护轮次的师傅放到保护列表
            if (vo.getDistributeNewCount() < protectionDefaultTimes) {
                // 设置派单方式: 1.相似 2.多技能 3.首轮优先 4.推荐分，默认为推荐分
                vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_PROTECTION_ORDINARY);
                vo.setDistributeRuleTitle("保");
                vo.setDistributeRuleText(String.format("多轮保护%d-%d", vo.getDistributeNewCount() + 1, protectionDefaultTimes));
                manyProtectionMasterList.add(vo);
            }
        }

        // 没有返回null
        if (CollectionUtils.isEmpty(manyProtectionMasterList)) {
            return null;
        }

        // 多轮保护排序
        this.sortMasterListByManyProtection(manyProtectionMasterList);

        return manyProtectionMasterList;
    }

    // 推荐权重分处理
    private List<ZsOrderDistributeVO> getRecommendScoreList(List<ZsOrderDistributeVO> waitProcessList) {

        // 设置标签
        for (ZsOrderDistributeVO vo : waitProcessList) {
            vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_RECOMMEND);
            vo.setDistributeRuleText("推荐权重分最高");
        }

        // 推荐权重分序排
        if (CollectionUtils.isNotEmpty(waitProcessList)) {
            this.sortMasterListByRecommendScore(waitProcessList);
        }

        return waitProcessList;
    }

    // 公平原则处理
    private List<ZsOrderDistributeVO> getFairRuleList(List<ZsOrderDistributeVO> waitProcessList) {

        // 设置标签
        for (ZsOrderDistributeVO vo : waitProcessList) {
            vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR);
            vo.setDistributeRuleText("公平原则");
        }

        // 公平原则序排
        if (CollectionUtils.isNotEmpty(waitProcessList)) {
            this.sortMasterListByFairRule(waitProcessList);
        }

        return waitProcessList;
    }

    // 公平原则处理 - 平台直派
    private List<ZsOrderDistributeVO> gridGetFairRuleList(List<ZsOrderDistributeVO> waitProcessList) {

        // 设置标签
        for (ZsOrderDistributeVO vo : waitProcessList) {
            vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR);
            vo.setDistributeRuleText("公平原则");
        }

        // 公平原则序排
        if (CollectionUtils.isNotEmpty(waitProcessList)) {
            this.gridSortMasterListByFairRule(waitProcessList);
        }

        return waitProcessList;
    }

    // 返修公平原则处理
    private List<ZsOrderDistributeVO> getFairReworkRuleList(List<ZsOrderDistributeVO> waitProcessList) {

        // 设置标签
        for (ZsOrderDistributeVO vo : waitProcessList) {
            vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR_REWORK);
            vo.setDistributeRuleText("返修公平原则");
        }

        // 返修公平原则序排
        if (CollectionUtils.isNotEmpty(waitProcessList)) {
            this.sortMasterListByFairReworkRule(waitProcessList);
        }

        return waitProcessList;
    }

    // 推荐条件过滤
    private List<ZsOrderDistributeVO> recommendSnapshotFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, List<ZsOrderDistributeVO> nonDistributeMasterList) {

        // 推荐师傅列表
        List<ZsOrderDistributeVO> recommendMasterList = Lists.newArrayListWithCapacity(masterList.size());

        // 把满足条件的师傅放到推荐权重分师傅列表

        for (ZsOrderDistributeVO vo : masterList ) {
            vo.setCheckMainSkill(Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId()));

            // 同时要满足:主技能，平台直派不限制
            if (distributeMasterQuery.isGridDistribute() || vo.getCheckMainSkill()) {
                recommendMasterList.add(vo);
            }
            else {
                nonDistributeMasterList.add(vo);
            }
        }

        return recommendMasterList;
    }

    // 推荐条件标记
    private void recommendSnapshotMarker(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        for (ZsOrderDistributeVO vo : masterList ) {
            vo.setCheckMainSkill(Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId()));
        }
    }

    // 校验工程师推荐派单原因
    private void checkMasterRecommendDistributeReason(ZsOrderDistributeVO vo, DistributeMasterQuery distributeMasterQuery, StringJoiner sj) {

        // 主技能
        if (!Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
            sj.add("主技能不匹配");
            //return "主技能不匹配";
        }

        //return null;
    }

    // 根据优先条件和评分规则对推荐工程师列表进行排序
    private List<ZsOrderDistributeVO> getSortScoreMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, List<ZsOrderDistributeVO> nonDistributeMasterList) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        // 用一个汇总列表来保存处理过的师傅，初始值为空
        List<ZsOrderDistributeVO> totalList = Lists.newArrayListWithCapacity(masterList.size());

        // 用一个新列表来保存当前待处理师傅，初始值为全部
        List<ZsOrderDistributeVO> waitProcessList = Lists.newArrayList(masterList);

        /*********************************************************************************************/

        /*** 1.已派相似订单 ***/

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = this.getDistributeSimilarOrderMasterList(waitProcessList, distributeMasterQuery, true);

        // 如果有相似已派订单的师傅,排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(distributeSimilarOrderMasterList)) {
            totalList.addAll(distributeSimilarOrderMasterList);
        }

        // 1.已派相似订单-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortScoreMasterList#:" + ",1.已派相似订单-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        /*** 2.未派相似订单-已派相似订单为空的情况下才处理 ***/

        if (CollectionUtils.isEmpty(distributeSimilarOrderMasterList)) {

            // 未派相似订单
            List<EsOrderWork> esOrderWorks = this.getUnDistributeSimilarWorkList(distributeMasterQuery);

            // 未派相似订单师傅列表
            List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = this.getUnDistributeSimilarOrderMasterList(esOrderWorks, waitProcessList, distributeMasterQuery, true);

            // 如果有相似未派订单的师傅,排序后的结果集添加到汇总列表
            if (CollectionUtils.isNotEmpty(unDistributeSimilarOrderMasterList)) {
                totalList.addAll(unDistributeSimilarOrderMasterList);
            }
        }

        // 2.未派相似订单-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortScoreMasterList#:" + ",2.未派相似订单-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        // 2.5 推荐条件过滤-服务商派单

        if (!distributeMasterQuery.isGridDistribute()) {
            waitProcessList = this.recommendSnapshotFilter(waitProcessList, distributeMasterQuery, nonDistributeMasterList);

            if (CollectionUtils.isEmpty(waitProcessList)) {
                logger.info("#getSortScoreMasterList#:" + ",推荐条件过滤后待处理列表为空，返回汇总结果");
                return totalList;
            }
        }

        /*** 3.首轮优先 ***/

        // 首轮师傅列表
        List<ZsOrderDistributeVO> firstOrderMasterList = this.getFirstOrderMasterList(waitProcessList, true);

        // 排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
            totalList.addAll(firstOrderMasterList);
        }

        // 3.首轮优先-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortScoreMasterList#:" + ",3.首轮优先-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        /*** 4.推荐权重分 ***/

        // 对剩下的待处理数据按推荐权重分规则处理
        List<ZsOrderDistributeVO> recommendScoreMasterList = this.getRecommendScoreList(waitProcessList);

        // 排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(recommendScoreMasterList)) {
            totalList.addAll(recommendScoreMasterList);
        }

        // 4.推荐权重分-end

        // 返回汇总的结果集
        return totalList;
    }

    // 根据优先条件和评分规则对公平工程师列表进行排序
    private List<ZsOrderDistributeVO> getSortFairMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, List<ZsOrderDistributeVO> nonDistributeMasterList) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        // 用一个汇总列表来保存处理过的师傅，初始值为空
        List<ZsOrderDistributeVO> totalList = Lists.newArrayListWithCapacity(masterList.size());

        // 用一个新列表来保存当前待处理师傅，初始值为全部
        List<ZsOrderDistributeVO> waitProcessList = Lists.newArrayList(masterList);

        /*********************************************************************************************/

        /*** 1.已派相似订单 ***/

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = this.getDistributeSimilarOrderMasterList(waitProcessList, distributeMasterQuery, true);

        // 如果有相似已派订单的师傅,排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(distributeSimilarOrderMasterList)) {
            totalList.addAll(distributeSimilarOrderMasterList);
        }

        // 1.已派相似订单-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortFairMasterList#:" + ",1.已派相似订单-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        /*** 2.未派相似订单-已派相似订单为空的情况下才处理 ***/

        if (CollectionUtils.isEmpty(distributeSimilarOrderMasterList)) {

            // 未派相似订单
            List<EsOrderWork> esOrderWorks = this.getUnDistributeSimilarWorkList(distributeMasterQuery);

            // 未派相似订单师傅列表
            List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = this.getUnDistributeSimilarOrderMasterList(esOrderWorks, waitProcessList, distributeMasterQuery, true);

            // 如果有相似未派订单的师傅,排序后的结果集添加到汇总列表
            if (CollectionUtils.isNotEmpty(unDistributeSimilarOrderMasterList)) {
                totalList.addAll(unDistributeSimilarOrderMasterList);
            }
        }

        // 2.未派相似订单-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortFairMasterList#:" + ",2.未派相似订单-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        // 2.5 推荐条件过滤-服务商派单

        if (!distributeMasterQuery.isGridDistribute()) {
            waitProcessList = this.recommendSnapshotFilter(waitProcessList, distributeMasterQuery, nonDistributeMasterList);

            if (CollectionUtils.isEmpty(waitProcessList)) {
                logger.info("#getSortScoreMasterList#:" + ",推荐条件过滤后待处理列表为空，返回汇总结果");
                return totalList;
            }
        }

        /*** 3.首轮优先 ***/

        // 首轮师傅列表
        List<ZsOrderDistributeVO> firstOrderMasterList = this.getFirstOrderMasterList(waitProcessList, true);

        // 排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
            totalList.addAll(firstOrderMasterList);
        }

        // 3.首轮优先-end.待处理列表为空，返回汇总结果
        if (CollectionUtils.isEmpty(waitProcessList)) {
            logger.info("#getSortFairMasterList#:" + ",3.首轮优先-end.待处理列表为空，返回汇总结果");
            return totalList;
        }

        /*** 4.公平原则 ***/

        // 对剩下的待处理数据按公平原则处理
        List<ZsOrderDistributeVO> fairRuleMasterList = this.getFairRuleList(waitProcessList);

        // 排序后的结果集添加到汇总列表
        if (CollectionUtils.isNotEmpty(fairRuleMasterList)) {
            totalList.addAll(fairRuleMasterList);
        }

        // 4.公平原则-end

        // 返回汇总的结果集
        return totalList;
    }

    // 获取自动推荐派单师傅
    private ZsOrderDistributeVO getAutoDistributeSimilarMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 1.已派相似订单 ***/

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = this.getDistributeSimilarOrderMasterList(masterList, distributeMasterQuery, false);

        // 如果有相似已派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(distributeSimilarOrderMasterList)) {
            ZsOrderDistributeVO vo = distributeSimilarOrderMasterList.get(0);

            // 记录派单快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SIMILAR);
            distributeSimilarOrderMasterList.remove(0);
            distributeSnapshotVO.setMasterList(distributeSimilarOrderMasterList);

            // 已派相似关联工单文案
            String distributeRelateWorkText = this.getDistributedSimilarRelateWorkText(masterList, distributeMasterQuery, vo.getMasterId());
            vo.setDistributeRelateWorkText(distributeRelateWorkText);

            return vo;
        }

        /*** 2.未派相似订单-已派相似订单为空的情况下才处理 ***/

        // 未派相似订单
        List<EsOrderWork> esOrderWorks = this.getUnDistributeSimilarWorkList(distributeMasterQuery);

        // 未派相似订单师傅列表
        List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = this.getUnDistributeSimilarOrderMasterList(esOrderWorks, masterList, distributeMasterQuery, false);

        // 如果有相似未派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(unDistributeSimilarOrderMasterList)) {
            ZsOrderDistributeVO vo = unDistributeSimilarOrderMasterList.get(0);

            // 记录派单快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_MULTI);
            unDistributeSimilarOrderMasterList.remove(0);
            distributeSnapshotVO.setMasterList(unDistributeSimilarOrderMasterList);

            // 未派相似关联工单文案
            String distributeRelateWorkText = this.getUnDistributeSimilarRelateWorkText(esOrderWorks);
            vo.setDistributeRelateWorkText(distributeRelateWorkText);

            return vo;
        }

        return null;
    }

    // 获取自动权重分派单师傅
    private ZsOrderDistributeVO getAutoDistributeScoreMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, DistributeArgsDRO distributeArgsDRO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        if (this.isManyProtection(distributeArgsDRO)) {

            // 多轮保护
            List<ZsOrderDistributeVO> manyProtectionMasterList = this.getAutoManyProtectionMasterList(masterList, distributeArgsDRO);

            // 如果有多轮保护的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(manyProtectionMasterList)) {
                ZsOrderDistributeVO vo = manyProtectionMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(vo.getDistributeRule());
                manyProtectionMasterList.remove(0);
                distributeSnapshotVO.setMasterList(manyProtectionMasterList);

                return vo;
            }
        }
        else {

            // 首轮师傅
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoFirstOrderMasterList(masterList, distributeMasterQuery);

            // 如果有首轮优先的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                firstOrderMasterList.remove(0);
                distributeSnapshotVO.setMasterList(firstOrderMasterList);

                return vo;
            }
        }


        // 按推荐权重分降序排序
        List<ZsOrderDistributeVO> recommendScoreMasterList = this.getRecommendScoreList(masterList);

        if (CollectionUtils.isNotEmpty(recommendScoreMasterList)) {
            ZsOrderDistributeVO vo = recommendScoreMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_RECOMMEND);
            recommendScoreMasterList.remove(0);
            distributeSnapshotVO.setMasterList(recommendScoreMasterList);

            return vo;
        }

        return null;
    }

    // 获取自动公平派单师傅
    private ZsOrderDistributeVO getAutoDistributeFairMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, DistributeArgsDRO distributeArgsDRO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        if (this.isManyProtection(distributeArgsDRO)) {

            // 多轮保护
            List<ZsOrderDistributeVO> manyProtectionMasterList = this.getAutoManyProtectionMasterList(masterList, distributeArgsDRO);

            // 如果有多轮保护的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(manyProtectionMasterList)) {
                ZsOrderDistributeVO vo = manyProtectionMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(vo.getDistributeRule());
                manyProtectionMasterList.remove(0);
                distributeSnapshotVO.setMasterList(manyProtectionMasterList);

                return vo;
            }
        }
        else {

            // 首轮师傅
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoFirstOrderMasterList(masterList, distributeMasterQuery);

            // 如果有首轮优先的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                firstOrderMasterList.remove(0);
                distributeSnapshotVO.setMasterList(firstOrderMasterList);

                return vo;
            }
        }

        // 按公平原则过滤和排序
        List<ZsOrderDistributeVO> fairRuleMasterList = this.getFairRuleList(masterList);

        if (CollectionUtils.isNotEmpty(fairRuleMasterList)) {
            ZsOrderDistributeVO vo = fairRuleMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR);
            fairRuleMasterList.remove(0);
            distributeSnapshotVO.setMasterList(fairRuleMasterList);

            return vo;
        }

        return null;
    }

    // 校验推荐派单原因
    private void checkRecommendDistributeReason(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, StringJoiner sj) {

        // 默认返回值
        //String reason = "没有工程师";

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            sj.add("没有工程师");
            //return reason;
        }

        /*** 1.已派相似订单 ***/

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = this.getDistributeSimilarOrderMasterList(masterList, distributeMasterQuery, false);

        // 如果有相似已派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(distributeSimilarOrderMasterList)) {
            return;
        }


        /*** 2.未派相似订单 ***/

        // 未派相似订单
        List<EsOrderWork> esOrderWorks = this.getUnDistributeSimilarWorkList(distributeMasterQuery);

        // 未派相似订单师傅列表
        List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = this.getUnDistributeSimilarOrderMasterList(esOrderWorks, masterList, distributeMasterQuery, false);

        // 如果有相似未派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(unDistributeSimilarOrderMasterList)) {
            return;
        }

        /*** 3.推荐条件 ***/

        // 非平台直派，校验工程师推荐派单原因
        if (!distributeMasterQuery.isGridDistribute()) {
            this.checkMasterRecommendDistributeReason(masterList.get(0), distributeMasterQuery, sj);

            /*if (reason != null) {
                return reason;
            }*/
        }

        // 3.推荐条件-end

        //return null;
    }

    /**
     * 计算推荐评分
     */
    private void calcRecommendScore(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeArgsDRO distributeArgsDRO) {

        // 转化为map
        Map<Integer, ZsOrderDistributeVO> masterStatMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));

        // 查询工程师绩效
        this.getMasterListPerf(masterStatMap);

        // 查询工程师服务分
        this.getMasterListServeScore(masterStatMap, distributeMasterQuery);

        // 计算评分
        masterStatMap.forEach((key, item) -> {
            item.setRecommendScore(this.getRecommendScore(item, distributeArgsDRO));
        });
    }

    /**
     * 根据相似规则排序
     */
    private void sortMasterListBySimilarRule(List<ZsOrderDistributeVO> masterList) {
        Collections.sort(masterList, (v1, v2) -> {

            // 都是主网格或者都不是主网格则比较距离
            if ((Objects.equals(v1.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN) && Objects.equals(v2.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN)) ||
                    (!Objects.equals(v1.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN) && !Objects.equals(v2.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN))) {
                BigDecimal distance1 = new BigDecimal(v1.getDistance() == null ? MAX_DISTANCE : v1.getDistance());
                BigDecimal distance2 = new BigDecimal(v2.getDistance() == null ? MAX_DISTANCE : v2.getDistance());

                int res = distance1.compareTo(distance2);
                return res;
            }

            // 主网格优先排序
            return Objects.equals(v1.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN) ? -1 : 1;
        });
    }

    /**
     * 根据昨天派单量排序
     *  2022-06-30 调整 增加分组优先、新手优先排序
     */
    private void sortMasterListByYesterdayDistributeCount(List<ZsOrderDistributeVO> masterList) {
        Collections.sort(masterList, (v1, v2) -> {
//            BigDecimal count1 = new BigDecimal(v1.getDatumPastDistributeCount());
//            BigDecimal count2 = new BigDecimal(v2.getDatumPastDistributeCount());
//            int res = count1.compareTo(count2);

            // 分组级别最小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            int res = groupId1.compareTo(groupId2);

            if (res != 0) {
                return res;
            }

            // 新手优先
            BigDecimal noviceStatus1 = new BigDecimal(v1.getNoviceStatus());
            BigDecimal noviceStatus2 = new BigDecimal(v2.getNoviceStatus());
            res = noviceStatus2.compareTo(noviceStatus1);

            if (res != 0) {
                return res;
            }

            // 昨日新单派单总量小优先
            BigDecimal yesterdayDistributeNewCount1 = new BigDecimal(v1.getYesterdayDistributeNewCount());
            BigDecimal yesterdayDistributeNewCount2 = new BigDecimal(v2.getYesterdayDistributeNewCount());
            res = yesterdayDistributeNewCount1.compareTo(yesterdayDistributeNewCount2);

            // 如果评分相等，距离近的优先
            if (res == 0) {
                BigDecimal distance1 = new BigDecimal(v1.getDistance() == null ? MAX_DISTANCE : v1.getDistance());
                BigDecimal distance2 = new BigDecimal(v2.getDistance() == null ? MAX_DISTANCE : v2.getDistance());
                res = distance1.compareTo(distance2);
            }

            return res;
        });
    }

    /**
     * 多轮保护排序
     */
    private void sortMasterListByManyProtection(List<ZsOrderDistributeVO> masterList) {

        // 今日新单派单总量小优先，昨日新单派单总量小优先，然后服务分高优先

        Collections.sort(masterList, (v1, v2) -> {

            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            int res = groupId1.compareTo(groupId2);

            if (res != 0) {
                return res;
            }

            // 今日新单派单总量小优先
            BigDecimal distributeNewCount1 = new BigDecimal(v1.getDistributeNewCount());
            BigDecimal distributeNewCount2 = new BigDecimal(v2.getDistributeNewCount());
            res = distributeNewCount1.compareTo(distributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 昨日新单派单总量小优先
            BigDecimal yesterdayDistributeNewCount1 = new BigDecimal(v1.getYesterdayDistributeNewCount());
            BigDecimal yesterdayDistributeNewCount2 = new BigDecimal(v2.getYesterdayDistributeNewCount());
            res = yesterdayDistributeNewCount1.compareTo(yesterdayDistributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 服务分越高越优先
            BigDecimal compositeScore1 = new BigDecimal(v1.getCompositeScore());
            BigDecimal compositeScore2 = new BigDecimal(v2.getCompositeScore());
            res = compositeScore2.compareTo(compositeScore1);

            return res;
        });
    }

    /**
     * 新手优先列表
     */
    private List<ZsOrderDistributeVO> noviceFirstMasterList(List<ZsOrderDistributeVO> masterList) {

        // 新手列表
        List<ZsOrderDistributeVO> noviceList = Lists.newArrayListWithCapacity(masterList.size());
        // 其他列表
        List<ZsOrderDistributeVO> otherList = Lists.newArrayListWithCapacity(masterList.size());

        // 总列表按新手标志拆分
        for (ZsOrderDistributeVO vo : masterList) {

            // 判断是否新手
            if (vo.getNovice() != null && vo.getNovice()) {
                noviceList.add(vo);
            }
            else {
                otherList.add(vo);
            }

        }

        // 分别根据昨天派单量排序
        this.sortMasterListByYesterdayDistributeCount(noviceList);
        this.sortMasterListByYesterdayDistributeCount(otherList);

        // 汇总到新列表
        List<ZsOrderDistributeVO> newList = Lists.newArrayListWithCapacity(masterList.size());
        newList.addAll(noviceList);
        newList.addAll(otherList);

        return newList;
    }

    /**
     * 根据推荐评分排序
     */
    private void sortMasterListByRecommendScore(List<ZsOrderDistributeVO> masterList) {

        // 推荐评分高的优先
        Collections.sort(masterList, (v1, v2) -> {
            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            int res = groupId1.compareTo(groupId2);

            if (res != 0) {
                return res;
            }

            BigDecimal score1 = new BigDecimal(v1.getRecommendScore());
            BigDecimal score2 = new BigDecimal(v2.getRecommendScore());
            res = score2.compareTo(score1);

            // 如果评分相等，距离近的优先
            if (res == 0) {
                BigDecimal distance1 = new BigDecimal(v1.getDistance() == null ? MAX_DISTANCE : v1.getDistance());
                BigDecimal distance2 = new BigDecimal(v2.getDistance() == null ? MAX_DISTANCE : v2.getDistance());
                res = distance1.compareTo(distance2);
            }

            return res;
        });
    }

    /**
     * 根据分层分级推荐评分排序
     */
    private void sortMasterListByGradingRecommendScore(List<ZsOrderDistributeVO> masterList) {

        // 分层排序单量少的优先 -> 分层优先级高的优先 -> 原推荐分逻辑
        Collections.sort(masterList, (v1, v2) -> {
            // 分层排序单量少的优先
            BigDecimal hierarchySortCount1 = new BigDecimal(Optional.ofNullable(v1.getHierarchySortCount()).orElse(0));
            BigDecimal hierarchySortCount2 = new BigDecimal(Optional.ofNullable(v2.getHierarchySortCount()).orElse(0));
            int res = hierarchySortCount1.compareTo(hierarchySortCount2);
            if (res != 0) {
                return res;
            }

            // 分层优先级高的优先
            BigDecimal priority1 = new BigDecimal(v1.getPriority());
            BigDecimal priority2 = new BigDecimal(v2.getPriority());
            res = priority1.compareTo(priority2);
            if (res != 0) {
                return res;
            }
            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            res = groupId1.compareTo(groupId2);

            if (res != 0) {
                return res;
            }

            BigDecimal score1 = new BigDecimal(v1.getRecommendScore());
            BigDecimal score2 = new BigDecimal(v2.getRecommendScore());
            res = score2.compareTo(score1);

            // 如果评分相等，距离近的优先
            if (res == 0) {
                BigDecimal distance1 = new BigDecimal(v1.getDistance() == null ? MAX_DISTANCE : v1.getDistance());
                BigDecimal distance2 = new BigDecimal(v2.getDistance() == null ? MAX_DISTANCE : v2.getDistance());
                res = distance1.compareTo(distance2);
            }

            return res;
        });
    }

    // 根据公平原则排序
    private void sortMasterListByFairRule(List<ZsOrderDistributeVO> masterList) {

        // 单时比小优先，今日新单派单总量小优先，昨日新单派单总量小优先，然后成功率高优先

        Collections.sort(masterList, (v1, v2) -> {

            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            int res = groupId1.compareTo(groupId2);

            if (res != 0) {
                return res;
            }

            // 单时比小优先
            BigDecimal datumOrderHourRatio1 = new BigDecimal(v1.getDatumOrderHourRatio());
            BigDecimal datumOrderHourRatio2 = new BigDecimal(v2.getDatumOrderHourRatio());
            res = datumOrderHourRatio1.compareTo(datumOrderHourRatio2);

            if (res != 0) {
                return res;
            }

            // 今日新单派单总量小优先
            BigDecimal distributeNewCount1 = new BigDecimal(v1.getDistributeNewCount());
            BigDecimal distributeNewCount2 = new BigDecimal(v2.getDistributeNewCount());
            res = distributeNewCount1.compareTo(distributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 昨日新单派单总量小优先
            BigDecimal yesterdayDistributeNewCount1 = new BigDecimal(v1.getYesterdayDistributeNewCount());
            BigDecimal yesterdayDistributeNewCount2 = new BigDecimal(v2.getYesterdayDistributeNewCount());
            res = yesterdayDistributeNewCount1.compareTo(yesterdayDistributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 成功率高优先
            BigDecimal successRate1 = new BigDecimal(v1.getSuccessRate());
            BigDecimal successRate2 = new BigDecimal(v2.getSuccessRate());
            res = successRate2.compareTo(successRate1);

            return res;
        });
    }

    // 根据公平原则排序 - 平台直派
    private void gridSortMasterListByFairRule(List<ZsOrderDistributeVO> masterList) {
        // 单时比小优先，今日新单派单总量小优先，昨日新单派单总量小优先，然后成功率高优先 最后组优先
        Collections.sort(masterList, (v1, v2) -> {

            // 单时比小优先
            BigDecimal datumOrderHourRatio1 = new BigDecimal(v1.getDatumOrderHourRatio());
            BigDecimal datumOrderHourRatio2 = new BigDecimal(v2.getDatumOrderHourRatio());
            int res = datumOrderHourRatio1.compareTo(datumOrderHourRatio2);

            if (res != 0) {
                return res;
            }

            // 今日新单派单总量小优先
            BigDecimal distributeNewCount1 = new BigDecimal(v1.getDistributeNewCount());
            BigDecimal distributeNewCount2 = new BigDecimal(v2.getDistributeNewCount());
            res = distributeNewCount1.compareTo(distributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 昨日新单派单总量小优先
            BigDecimal yesterdayDistributeNewCount1 = new BigDecimal(v1.getYesterdayDistributeNewCount());
            BigDecimal yesterdayDistributeNewCount2 = new BigDecimal(v2.getYesterdayDistributeNewCount());
            res = yesterdayDistributeNewCount1.compareTo(yesterdayDistributeNewCount2);

            if (res != 0) {
                return res;
            }

            // 成功率高优先
            BigDecimal successRate1 = new BigDecimal(v1.getSuccessRate());
            BigDecimal successRate2 = new BigDecimal(v2.getSuccessRate());
            res = successRate2.compareTo(successRate1);


            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            res = groupId1.compareTo(groupId2);

            return res;
        });
    }

    // 根据家电突破-公平规则排序 - 平台直派
    private void gridSortMasterListByHomeAppliancesFairRule(List<ZsOrderDistributeVO> masterList) {
        // 今日家电突破派单量小的优先 最后组优先
        Collections.sort(masterList, (v1, v2) -> {
            // 今日家电突破派单量小的优先
            BigDecimal breakoutDistributeCount1 = new BigDecimal(v1.getBreakoutDistributeCount());
            BigDecimal breakoutDistributeCount2 = new BigDecimal(v2.getBreakoutDistributeCount());
            int res = breakoutDistributeCount1.compareTo(breakoutDistributeCount2);

            if (res != 0) {
                return res;
            }

            // 分级级别小的优先
            BigDecimal groupId1 = new BigDecimal(v1.getGroupId());
            BigDecimal groupId2 = new BigDecimal(v2.getGroupId());
            res = groupId1.compareTo(groupId2);

            return res;
        });
    }


    // 根据返修公平原则排序
    private void sortMasterListByFairReworkRule(List<ZsOrderDistributeVO> masterList) {

        // 当月已派他人返修-->服务分，月派他人返修越小越优先，服务分越高越优先

        Collections.sort(masterList, (v1, v2) -> {

            // 月派他人返修越小越优先
            BigDecimal monthReworkCount1 = new BigDecimal(v1.getMonthReworkCount());
            BigDecimal monthReworkCount2 = new BigDecimal(v2.getMonthReworkCount());
            int res = monthReworkCount1.compareTo(monthReworkCount2);

            if (res != 0) {
                return res;
            }

            // 服务分越高越优先
            BigDecimal compositeScore1 = new BigDecimal(v1.getCompositeScore());
            BigDecimal compositeScore2 = new BigDecimal(v2.getCompositeScore());
            res = compositeScore2.compareTo(compositeScore1);

            return res;
        });
    }

    // 根据返修优先原则排序
    private void sortReworkOriginalEngineerPriority(List<ReworkOriginalEngineerBO> masterList) {

        // 最优先-->服务完成时间最小-->主从工程师

        Collections.sort(masterList, (v1, v2) -> {

            // 是否为最优先
            BigDecimal firstPriority1 = new BigDecimal(v1.getFirstPriority());
            BigDecimal firstPriority2 = new BigDecimal(v2.getFirstPriority());
            int res = firstPriority2.compareTo(firstPriority1);

            if (res != 0) {
                return res;
            }

            // 服务完成时间最小
            BigDecimal completeTime1 = new BigDecimal(v1.getCompleteTime().getTime());
            BigDecimal completeTime2 = new BigDecimal(v2.getCompleteTime().getTime());
            res = completeTime1.compareTo(completeTime2);

            if (res != 0) {
                return res;
            }

            // 主从工程师
            BigDecimal engineerType1 = new BigDecimal(v1.getOrderEngineerType());
            BigDecimal engineerType2 = new BigDecimal(v2.getOrderEngineerType());
            res = engineerType1.compareTo(engineerType2);


            return res;
        });
    }



    /**
     * 查询工程师绩效
     *
     * @param masterStatMap
     */
    private void getMasterListPerf(Map<Integer, ZsOrderDistributeVO> masterStatMap) {
        try {
            List<Integer> masterIdList = new ArrayList(masterStatMap.keySet());

            // 调用工程师绩效服务
            ResponseDTO<List<DistributeMetricsDRO>> responseDTO = distributeMetricsListRemoteService.listDistributeMetricsByMasterIds(masterIdList);
            if (!responseDTO.isSuccess() || responseDTO.getData() == null || CollectionUtils.isEmpty(responseDTO.getData())) {
                return;
            }

            List<DistributeMetricsDRO> masterPerfList = responseDTO.getData();

            // 把结果保存到vo
            for (DistributeMetricsDRO dro : masterPerfList) {
                ZsOrderDistributeVO vo = masterStatMap.get(dro.getMasterId());

                if (vo != null) {
                    // 把绩效结果保存为整数，便于推荐分计算
                    vo.setSuccessRate(dro.getSuccessRate() == null ? 0 : dro.getSuccessRate());
                    vo.setVisitRate(dro.getVisitRate() == null ? 0 : dro.getVisitRate());
                    vo.setAtvAvg(dro.getAtv() == null ? 0 : dro.getAtv());
                }
            }
        } catch (Exception ex) {
            logger.error("distributeMetricsListRemoteService#listDistributeMetricsByMasterIds：", ex);
        }
    }

    /**
     * 已派单-相似订单工程师列表
     *
     * @param masterList
     * @param distributeMasterQuery
     * @return
     */
    private List<Integer> getDistributedSimilarOrderMasterId(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        //logger.info("相似订单工程师列表");

        // 预约时间 或 经纬度为空 则为不相似单
        Double latitude = distributeMasterQuery.getLatitude();
        Double longitude = distributeMasterQuery.getLongitude();
        Date dutyTime = distributeMasterQuery.getDutyTime();

        if (Objects.isNull(latitude) || Objects.isNull(longitude) || Objects.isNull(dutyTime)) {
            return Lists.newArrayList();
        }

        // region 查询条件
        // 相似订单需要与当前订单条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 状态结果：已派单-已领单-已上门-服务完成 / 进行中
        boolQueryBuilder.must(QueryBuilders.termsQuery("status",
                Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE)));
        boolQueryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

        // 新单，返修单
        boolQueryBuilder.must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));

        // 订单距离 <= 2KM
        boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("contact.location").distance("2km").point(latitude, longitude));

        // 用户电话
        List<String> phoneList = Lists.newArrayListWithCapacity(3);
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone())) {
            phoneList.add(distributeMasterQuery.getTelephone());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone2())) {
            phoneList.add(distributeMasterQuery.getTelephone2());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone3())) {
            phoneList.add(distributeMasterQuery.getTelephone3());
        }

        if (CollectionUtils.isNotEmpty(phoneList)) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)));
        }

        // 废弃：预约时间间隔 <=1.5 小时 （预约时间 range (当前订单预约时间-1.5小时, 当前订单预约时间+1.5小时)）
        //        Date endTime = DateUtil.addMinute(dutyTime, 90);
        //        Date startTime = DateUtil.addMinute(dutyTime, -90);
        //        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(DateUtil.toString(startTime)).lte
        //        (DateUtil.toString(endTime)));

        // 预约时间同一天
//        String dutyStartTimeStr = DateUtil.toString(DateUtil.getDateStart(dutyTime));
//        String dutyEndTimeStr = DateUtil.toString(DateUtil.getDateEnd(dutyTime));
//        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(dutyStartTimeStr).lte(dutyEndTimeStr));

        // 包含工程师条件 （可选）
        if (CollectionUtils.isNotEmpty(masterList)) {
            Set<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toSet());
            boolQueryBuilder.must(QueryBuilders.termsQuery("masterId", masterIdList));
        }

        // 排除当前订单
        Long orderId = distributeMasterQuery.getOrderId();
        if (NumberUtil.isNotNullOrZero(orderId)) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("orderId", orderId));
        }

        // PS:根据是否网格化派单分别处理
        if (!distributeMasterQuery.isGridDistribute()) {
            // 服务公司
            boolQueryBuilder.must(QueryBuilders.termQuery("companyId", distributeMasterQuery.getCompanyId()));
            boolQueryBuilder.must(QueryBuilders.termQuery("manageCompanyId", distributeMasterQuery.getManageCompanyId()));
        }

        // endregion

        // region 聚合条件
        // 工程师分组
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("master_id_group").field("masterId").size(10000);
        // endregion

        // region 构建查询对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        if (logger.isDebugEnabled()) {
            logger.debug("boolQueryBuilder:[{}]", boolQueryBuilder.toString());
        }

        // 将搜索条件设置到构建中
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        // 将工程师分组设置到构建中
        nativeSearchQueryBuilder.addAggregation(termsAggregationBuilder);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 100));

        if (logger.isDebugEnabled()) {
            logger.debug("nativeSearchQueryBuilder:[{}]", JSON.toJSONString(nativeSearchQueryBuilder));
        }

        // 生产NativeSearchQuery
        NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();

        if (logger.isDebugEnabled()) {
            logger.debug("NativeSearchQuery:[{}]", JSON.toJSONString(searchQuery));
        }

        try {
            Aggregations aggregations = orderWorkEsBService.getAggregationsByQuery(searchQuery);
            // endregion

            // region 聚合结果处理
            //转换成map集合
            // Map<String, Aggregation> aggregationMap = aggregations.asMap();
            //获得对应的聚合函数的聚合子类，该聚合子类也是个map集合,里面的value就是桶Bucket，我们要获得Bucket
            ParsedTerms longTerms = aggregations.get("master_id_group");

            //获得所有的桶
            List<? extends Terms.Bucket> buckets = longTerms.getBuckets();
            if (CollectionUtils.isEmpty(buckets)) {
                return Lists.newArrayList();
            }

            List<Integer> masterIdList = buckets.stream().map(e -> Integer.valueOf(e.getKeyAsString())).collect(Collectors.toList());
            // endregion

            return masterIdList;
        } catch (Exception ex) {
            logger.error("查询 已派单-相似订单工程师列表 错误：{}", ex);
        }

        return Lists.newArrayList();
    }

    /**
     * 已派工单ID列表
     *
     * @param masterList
     * @param distributeMasterQuery
     * @param masterId
     * @return
     */
    private List<Long> getDistributedSimilarWorkIdList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, Integer masterId) {

        // 预约时间 或 经纬度为空 则为不相似单
        Double latitude = distributeMasterQuery.getLatitude();
        Double longitude = distributeMasterQuery.getLongitude();
        Date dutyTime = distributeMasterQuery.getDutyTime();

        if (Objects.isNull(latitude) || Objects.isNull(longitude) || Objects.isNull(dutyTime)) {
            return Lists.newArrayListWithCapacity(0);
        }

        // region 查询条件
        // 相似订单需要与当前订单条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 基础条件： 工程师
        boolQueryBuilder.must(QueryBuilders.termQuery("masterId", masterId));

        // 状态结果：已派单-已领单-已上门-服务完成 / 进行中
        boolQueryBuilder.must(QueryBuilders.termsQuery("status",
                Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE)));
        boolQueryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

        // 新单，返修单
        boolQueryBuilder.must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));

        // 订单距离 <= 2KM
        boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("contact.location").distance("2km").point(latitude, longitude));

        // 用户电话
        List<String> phoneList = Lists.newArrayListWithCapacity(3);
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone())) {
            phoneList.add(distributeMasterQuery.getTelephone());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone2())) {
            phoneList.add(distributeMasterQuery.getTelephone2());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone3())) {
            phoneList.add(distributeMasterQuery.getTelephone3());
        }

        if (CollectionUtils.isNotEmpty(phoneList)) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)));
        }

        // 预约时间同一天
//        String dutyStartTimeStr = DateUtil.toString(DateUtil.getDateStart(dutyTime));
//        String dutyEndTimeStr = DateUtil.toString(DateUtil.getDateEnd(dutyTime));
//        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(dutyStartTimeStr).lte(dutyEndTimeStr));

        // 包含工程师条件 （可选）
        if (CollectionUtils.isNotEmpty(masterList)) {
            Set<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toSet());
            boolQueryBuilder.must(QueryBuilders.termsQuery("masterId", masterIdList));
        }

        // 排除当前订单
        Long orderId = distributeMasterQuery.getOrderId();
        if (NumberUtil.isNotNullOrZero(orderId)) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("orderId", orderId));
        }

        // PS:根据是否网格化派单分别处理
        if (!distributeMasterQuery.isGridDistribute()) {
            boolQueryBuilder.must(QueryBuilders.termQuery("companyId", distributeMasterQuery.getCompanyId()));
            boolQueryBuilder.must(QueryBuilders.termQuery("manageCompanyId", distributeMasterQuery.getManageCompanyId()));
        }

        // endregion

        // region 查询workId列表
        NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 100));
        String[] columns = {"id"};
        SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
        searchQuery.addSourceFilter(sourceFilter);

        try {
            List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(searchQuery);
            if (org.springframework.util.CollectionUtils.isEmpty(esOrderWorks)) {
                return Lists.newArrayListWithCapacity(0);
            }

            List<Long> workIds = Lists.newArrayListWithCapacity(esOrderWorks.size());
            esOrderWorks.forEach(esOrderWork -> {
                workIds.add(esOrderWork.getId());
            });

            return workIds;
        } catch (Exception ex) {
            logger.error("查询已派工单ID列表 错误：{}", ex);
        }
        // endregion

        return Lists.newArrayListWithCapacity(0);
    }

    /**
     * 未派相似工单列表
     *
     * @param distributeMasterQuery
     * @return List<EsOrderWork>
     */
    private List<EsOrderWork> getUnDistributeSimilarWorkList(DistributeMasterQuery distributeMasterQuery) {
        //logger.info("未派相似工单列表");

        // 预约时间 或 经纬度为空 则为不相似单
        Double latitude = distributeMasterQuery.getLatitude();
        Double longitude = distributeMasterQuery.getLongitude();
        Date dutyTime = distributeMasterQuery.getDutyTime();

        if (Objects.isNull(latitude) || Objects.isNull(longitude) || Objects.isNull(dutyTime)) {
            return Lists.newArrayListWithCapacity(0);
        }

        // region 查询条件

        // 相似订单需要与当前订单条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 状态结果：进行中
        boolQueryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

        // 新单，返修单
        boolQueryBuilder.must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));

        // 订单距离 <= 2KM
        boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("contact.location").distance("2km").point(latitude, longitude));

        // 用户电话
        List<String> phoneList = Lists.newArrayListWithCapacity(3);
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone())) {
            phoneList.add(distributeMasterQuery.getTelephone());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone2())) {
            phoneList.add(distributeMasterQuery.getTelephone2());
        }
        if (StringUtils.isNotBlank(distributeMasterQuery.getTelephone3())) {
            phoneList.add(distributeMasterQuery.getTelephone3());
        }

        if (CollectionUtils.isNotEmpty(phoneList)) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)));
        }

        // 废弃：预约时间间隔 <=1.5 小时 （预约时间 range (当前订单预约时间-1.5小时, 当前订单预约时间+1.5小时)）
        //        Date endTime = DateUtil.addMinute(dutyTime, 90);
        //        Date startTime = DateUtil.addMinute(dutyTime, -90);
        //        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(DateUtil.toString(startTime)).lte
        //        (DateUtil.toString(endTime)));

        // 预约时间同一天
//        String dutyStartTimeStr = DateUtil.toString(DateUtil.getDateStart(dutyTime));
//        String dutyEndTimeStr = DateUtil.toString(DateUtil.getDateEnd(dutyTime));
//        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(dutyStartTimeStr).lte(dutyEndTimeStr));

        // 排除本单
        Long orderId = distributeMasterQuery.getOrderId();
        if (Objects.nonNull(orderId)) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("orderId", orderId));
        }

        // PS:根据是否网格化派单分别处理
        if (distributeMasterQuery.isGridDistribute()) {
            // 状态：已确认
            boolQueryBuilder.must(QueryBuilders.termsQuery("status", Lists.newArrayList(OrderStatusConsts.WORK_STATUS_CONFIRM)));
        }
        else {
            // 状态：已分单
            boolQueryBuilder.must(QueryBuilders.termsQuery("status", Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ASSIGN)));
            // 公司ID
            boolQueryBuilder.must(QueryBuilders.termQuery("companyId", distributeMasterQuery.getCompanyId()));
            boolQueryBuilder.must(QueryBuilders.termQuery("manageCompanyId", distributeMasterQuery.getManageCompanyId()));
        }

        // endregion

        // region 查询work列表

        NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 100));
        String[] columns = {"id", "productId", "showProductId", "servCategId", "categTwoId"};
        SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
        searchQuery.addSourceFilter(sourceFilter);

        try {
            List<EsOrderWork> page = orderWorkEsBService.listPageByQuery(searchQuery);
            return page;
        } catch (Exception ex) {
            logger.error("查询未派相似工单列表 错误：{}", ex);
        }

        // endregion

        return Lists.newArrayListWithCapacity(0);
    }

    /**
     * 已派工单ID列表文案
     *
     * @param masterList
     * @param distributeMasterQuery
     * @param masterId
     * @return
     */
    private String getDistributedSimilarRelateWorkText(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, Integer masterId) {
        List<Long> workIds = this.getDistributedSimilarWorkIdList(masterList, distributeMasterQuery, masterId);
        if (CollectionUtils.isEmpty(workIds)) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        sb.append("已派相似工单号：");
        for (int i = 0; i < workIds.size(); i++) {
            if (i > 0) {
                sb.append("、");
            }

            sb.append(workIds.get(i));
        }

        return sb.toString();
    }

    /**
     * 未派工单ID列表文案
     *
     * @param esOrderWorks
     * @return
     */
    private String getUnDistributeSimilarRelateWorkText(List<EsOrderWork> esOrderWorks) {
        if (CollectionUtils.isEmpty(esOrderWorks)) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        sb.append("未派相似工单号：");
        for (int i = 0; i < esOrderWorks.size(); i++) {
            if (i > 0) {
                sb.append("、");
            }

            sb.append(esOrderWorks.get(i).getId());
        }

        return sb.toString();
    }

    /**
     * 查询派单总览表
     *
     * @param masterList
     * @param distributeMasterQuery
     * @return
     */
    private List<ZsOrderDistributeVO> getMasterListWorkInfo(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 转化为map
        Map<Integer, ZsOrderDistributeVO> masterStatMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));

        Date queryDate;
        String fieldName;

        // 没有预约时间就用派单时间查询
        if (distributeMasterQuery.getDutyTime() == null) {
            queryDate = DateUtil.getNow();
            fieldName = "distributeTime";
        } else {
            queryDate = distributeMasterQuery.getDutyTime();
            fieldName = "dutyTime";
        }

        // 调用绩效派单总览表接口
        MasterOverviewDIO masterOverviewDIO = new MasterOverviewDIO();
        masterOverviewDIO.setCityId(distributeMasterQuery.getCityId());
        masterOverviewDIO.setExcludeOrderId(distributeMasterQuery.getOrderId());
        masterOverviewDIO.setDatumDate(queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
        masterOverviewDIO.setField(fieldName);
        masterOverviewDIO.setMasterIdList(masterStatMap.keySet().stream().collect(Collectors.toList()));

        // 非网格化派单设置服务商
//        if (!distributeMasterQuery.isGridDistribute()) {
//            masterOverviewDIO.setManageCompanyId(distributeMasterQuery.getManageCompanyId());
//        }

        logger.info("masterOverviewListRemoteService#listIntegrateByDio:{}", JSON.toJSONString(masterOverviewDIO));
        ResponseDTO<List<MasterOverviewIntegrateDRO>> responseDTO = masterOverviewListRemoteService.listIntegrateByDio(masterOverviewDIO);
        logger.info("masterOverviewListRemoteService#listIntegrateByDio[responseDTO]:{}", JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess() || CollectionUtils.isEmpty(responseDTO.getData())) {
            return masterList;
        }

        for (MasterOverviewIntegrateDRO dro : responseDTO.getData()) {

            ZsOrderDistributeVO vo = masterStatMap.get(dro.getMasterId());

            if (vo != null) {
                vo.setHandCount(dro.getDoingCount() == null ? 0 : dro.getDoingCount());
                vo.setHandReworkCount(dro.getDoingReworkCount() == null ? 0 : dro.getDoingReworkCount());
                vo.setMonthReworkCount(dro.getCurrentMonthDistributeOtherReworkCount() == null ? 0 : dro.getCurrentMonthDistributeOtherReworkCount());
                vo.setTodaySuccessCount(dro.getCompleteCount() == null ? 0 : dro.getCompleteCount());
                vo.setDistributeNewCount(dro.getDistributeNewCount() == null ? 0 : dro.getDistributeNewCount());
                vo.setYesterdayDistributeNewCount(dro.getYesterdayDistributeNewCount() == null ? 0 : dro.getYesterdayDistributeNewCount());
                vo.setDatumDistributeCount(dro.getDatumDistributeCount() == null ? 0 : dro.getDatumDistributeCount());
                vo.setDatumDoingCount(dro.getDatumDoingCount() == null ? 0 : dro.getDatumDoingCount());
                vo.setDatumDistributeDutyCount(dro.getDatumDistributeDutyCount() == null ? 0 : dro.getDatumDistributeDutyCount());
                vo.setDatumPastDistributeCount(dro.getDatumPastDistributeCount() == null ? 0 : dro.getDatumPastDistributeCount());
                vo.setDatumOrderHourRatio(dro.getDatumOrderHourRatio() == null ? 0 : dro.getDatumOrderHourRatio());
                vo.setDeliveryAndWaitPartCount(dro.getDeliveryAndWaitPartCount() == null ? 0 : dro.getDeliveryAndWaitPartCount());
                vo.setOutGridCount(dro.getOutGridCount() == null ? 0 : dro.getOutGridCount());
                vo.setSysAcrossGridCount(dro.getSysAcrossGridCount() == null ? 0 : dro.getSysAcrossGridCount());
                vo.setYesterdayTiltDistributeCount(dro.getYesterdayTiltDistributeCount() == null ? 0 : dro.getYesterdayTiltDistributeCount());
                vo.setBreakoutDistributeCount(dro.getBreakoutDistributeCount() == null ? 0 : dro.getBreakoutDistributeCount());
                vo.setYesterdayBreakoutDistributeCount(dro.getYesterdayBreakoutDistributeCount() == null ? 0 : dro.getYesterdayBreakoutDistributeCount());
                vo.setRedistributeCount(dro.getRedistributeCount() == null ? 0 : dro.getRedistributeCount());
                vo.setFalseRedistributeScore(dro.getFalseRedistributeScore() == null ? 0 : dro.getFalseRedistributeScore());
                vo.setFalseCancelScore(dro.getFalseCancelScore() == null ? 0 : dro.getFalseCancelScore());
                vo.setReworkReminderCount(dro.getReworkReminderCount() == null ? 0 : dro.getReworkReminderCount());
                vo.setReworkOtherRewardCount(dro.getReworkOtherRewardCount() == null ? 0 : dro.getReworkOtherRewardCount());
            }

        }

        return masterList;
    }

    /**
     * 获取派单总览指标map
     */
    private Map<Integer, MasterOverviewIntegrateDRO> getDistributeOverviewInfoMap(List<Integer> engineerIds, Integer cityId, Long orderId, Date dutyTime) {
        Date queryDate;
        String fieldName;
        // 没有预约时间就用派单时间查询
        if (dutyTime == null) {
            queryDate = DateUtil.getNow();
            fieldName = "distributeTime";
        } else {
            queryDate = dutyTime;
            fieldName = "dutyTime";
        }

        // 调用绩效派单总览表接口
        MasterOverviewDIO masterOverviewDIO = new MasterOverviewDIO();
        masterOverviewDIO.setCityId(cityId);
        masterOverviewDIO.setExcludeOrderId(orderId);
        masterOverviewDIO.setDatumDate(queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
        masterOverviewDIO.setField(fieldName);
        masterOverviewDIO.setMasterIdList(engineerIds);

        logger.info("masterOverviewListRemoteService#listIntegrateByDio:{}", JSON.toJSONString(masterOverviewDIO));
        ResponseDTO<List<MasterOverviewIntegrateDRO>> responseDTO = masterOverviewListRemoteService.listIntegrateByDio(masterOverviewDIO);
        logger.info("masterOverviewListRemoteService#listIntegrateByDio[responseDTO]:{}", JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess() || CollectionUtils.isEmpty(responseDTO.getData())) {
            return Collections.emptyMap();
        }
        return responseDTO.getData().stream().collect(Collectors.toMap(MasterOverviewIntegrateDRO::getMasterId, e -> e, (k1, k2) -> k1));
    }

    /**
     * 获取自然周数据
     * @param masterList
     * @param distributeMasterQuery
     * @return
     */
    private List<ZsOrderDistributeVO> getMasterListNatureWeekInfo(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 转化为map
        Map<Integer, ZsOrderDistributeVO> masterStatMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));

        MasterOverviewHistoryDIO dio = new MasterOverviewHistoryDIO();
        dio.setCityId(distributeMasterQuery.getCityId());
        List<EngineerInfoDIO> infoDIOS = masterList.stream().map(master -> {
            EngineerInfoDIO infoDIO = new EngineerInfoDIO();
            infoDIO.setEngineerId(master.getMasterId());
            infoDIO.setProductGroupId(master.getProductGroupId());
            infoDIO.setManageCompanyId(master.getSpId());
            return infoDIO;
        }).collect(Collectors.toList());
        dio.setEngineerInfoList(infoDIOS);

        logger.info("masterOverviewListRemoteService#listNatureWeekDataByDIO:{}", JSON.toJSONString(dio));
        ResponseDTO<List<MasterOverviewHistoryDRO>> listResponseDTO = masterOverviewListRemoteService.listNatureWeekDataByDIO(dio);
        logger.info("masterOverviewListRemoteService#listNatureWeekDataByDIO[responseDTO]:{}", JSON.toJSONString(listResponseDTO));

        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return masterList;
        }

        for (MasterOverviewHistoryDRO dro : listResponseDTO.getData()) {
            ZsOrderDistributeVO vo = masterStatMap.get(dro.getEngineerId());
            if (vo != null) {
                vo.setNatureWeekDistributeNewCount(Optional.ofNullable(dro.getDistributeNewCount()).orElse(0));
                vo.setSleepVirtualCount(Optional.ofNullable(dro.getSleepVirtualCount()).orElse(0));
                vo.setTodaySleepVirtualCount(Optional.ofNullable(dro.getTodaySleepVirtualCount()).orElse(0));
            }
        }

        return masterList;
    }

    /**
     * 获取工程师基础信息map
     */
    private Map<Integer, ForeignEngineerBasicInfoDRO> getEngineerInfoMap(Set<Integer> engineerIdSet) {
        ResponseDTO<List<ForeignEngineerBasicInfoDRO>> listResponseDTO = engineerListRemoteService.listEngineerByIdSet(engineerIdSet);
        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return Collections.emptyMap();
        }
        return listResponseDTO.getData().stream().collect(Collectors.toMap(ForeignEngineerBasicInfoDRO::getEngineerId, e -> e, (k1, k2) -> k1));
    }

    /**
     * 查询工程师服务分
     *
     * @param masterStatMap
     * @param distributeMasterQuery
     * @return
     */
    private void getMasterListServeScore(Map<Integer, ZsOrderDistributeVO> masterStatMap, DistributeMasterQuery distributeMasterQuery) {
        EngineerProductGroupCompositeScoreForDispatchOrderDIO engineerProductGroupCompositeScoreForDispatchOrderDIO = new EngineerProductGroupCompositeScoreForDispatchOrderDIO();

        engineerProductGroupCompositeScoreForDispatchOrderDIO.setEngineerIds(masterStatMap.keySet().stream().collect(Collectors.toList()));
        engineerProductGroupCompositeScoreForDispatchOrderDIO.setProductGroupId(distributeMasterQuery.getServProductGroupId());
        engineerProductGroupCompositeScoreForDispatchOrderDIO.setCityId(distributeMasterQuery.getCityId());
        logger.info("compositeServeScoreForOmsListRemoteService#listEngineerProductGroupCompositeScores 入参：{}", engineerProductGroupCompositeScoreForDispatchOrderDIO);
        ResponseDTO<List<EngineerProductGroupCompositeScoreForDispatchOrderDRO>> responseDTO = compositeServeScoreForOmsListRemoteService.listEngineerProductGroupCompositeScores(engineerProductGroupCompositeScoreForDispatchOrderDIO);
        logger.info("compositeServeScoreForOmsListRemoteService#listEngineerProductGroupCompositeScores 出参：{}", responseDTO);
        if (!responseDTO.isSuccess() || CollectionUtils.isEmpty(responseDTO.getData())) {
            return;
        }

        for (EngineerProductGroupCompositeScoreForDispatchOrderDRO dro : responseDTO.getData()) {
            ZsOrderDistributeVO vo = masterStatMap.get(dro.getEngineerId());

            if (vo != null) {
                vo.setCompositeScore(dro.getCompositeScore() == null ? 0 : dro.getCompositeScore().setScale( 0, BigDecimal.ROUND_DOWN ).intValue());
                vo.setHighGradeFlag(dro.getHighGradeFlag() == null ? 1 : dro.getHighGradeFlag());
            }
        }
    }

    /**
     * 查询工程师工作时长
     */
    private void getMasterListWorkingTimes(List<ZsOrderDistributeVO> masterList) {
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 将工程师id转换为Set
        Set<Integer> masterIdSet = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toSet());
        // todo fubiao
        logger.info("getMasterListWorkingTimes#listWorkingTimesByIds 入参 [{}]",JSON.toJSONString(masterIdSet));
        ResponseDTO<List<WorkingTimeDRO>> responseDTO = scheduleListRemoteService.listWorkingTimesByIds(masterIdSet, new Date());
        logger.info("getMasterListWorkingTimes#listWorkingTimesByIds 出参 [{}]",JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess() || CollectionUtils.isEmpty(responseDTO.getData())) {
            return;
        }

        // 转化为map
        Map<Integer, ZsOrderDistributeVO> masterStatMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));

        for (WorkingTimeDRO dro : responseDTO.getData()) {
            ZsOrderDistributeVO vo = masterStatMap.get(dro.getEngineerId());

            if (vo != null) {
                vo.setScheduleHours(dro.getScheduleHours());
                vo.setSleepHours(dro.getSleepHours());
                vo.setWorkingHours(dro.getWorkingHours());
            }
        }
    }

    //查询统计信息部分结束******************************************************************************************************//

    //计算推荐分部分开始******************************************************************************************************//

    /**
     * 获取评分
     *
     * @return
     */
    private double getRecommendScore(ZsOrderDistributeVO vo, DistributeArgsDRO distributeArgsDRO) {

        // 默认权重
        int distanceWeight = 40;
        int handOrderWeight = 30;
        int distributeNewCountWeight = 30;
        int starLevelScoreWeight = 0;
        int serveScoreWeight = 0;
        int datumOrderHourRatioWeight = 0;

        // 从派单参数获取，直营和非直营工程师分别采用不同权重
        if (distributeArgsDRO != null) {

            // 直营
            if (Objects.equals(vo.getAgent(), GlobalConsts.NO)) {
                if (distributeArgsDRO.getDistanceWeight() != null) {
                    distanceWeight = distributeArgsDRO.getDistanceWeight();
                }

                if (distributeArgsDRO.getHandlerWeight() != null) {
                    handOrderWeight = distributeArgsDRO.getHandlerWeight();
                }

                if (distributeArgsDRO.getDistributeNewCount() != null) {
                    distributeNewCountWeight = distributeArgsDRO.getDistributeNewCount();
                }

                if (distributeArgsDRO.getStarLevelScoreWeight() != null) {
                    starLevelScoreWeight = distributeArgsDRO.getStarLevelScoreWeight();
                }

                if (distributeArgsDRO.getServeScore() != null) {
                    serveScoreWeight = distributeArgsDRO.getServeScore();
                }

                if (distributeArgsDRO.getDatumOrderHourRatio() != null) {
                    datumOrderHourRatioWeight = distributeArgsDRO.getDatumOrderHourRatio();
                }
            }
            // 非直营
            else {
                if (distributeArgsDRO.getDistanceWeightNon() != null) {
                    distanceWeight = distributeArgsDRO.getDistanceWeightNon();
                }

                if (distributeArgsDRO.getHandlerWeightNon() != null) {
                    handOrderWeight = distributeArgsDRO.getHandlerWeightNon();
                }

                if (distributeArgsDRO.getDistributeNewCountNon() != null) {
                    distributeNewCountWeight = distributeArgsDRO.getDistributeNewCountNon();
                }

                if (distributeArgsDRO.getStarLevelScoreWeightNon() != null) {
                    starLevelScoreWeight = distributeArgsDRO.getStarLevelScoreWeightNon();
                }

                if (distributeArgsDRO.getServeScoreNon() != null) {
                    serveScoreWeight = distributeArgsDRO.getServeScoreNon();
                }

                if (distributeArgsDRO.getDatumOrderHourRatioNon() != null) {
                    datumOrderHourRatioWeight = distributeArgsDRO.getDatumOrderHourRatioNon();
                }
            }
        }

        // 计算距离评分
        double distanceRS = this.getDistanceRecommendScore(vo.getDistance(), distanceWeight);
        // 计算手头单评分
        double handOrderRS = this.getHandOrderRecommendScore(vo, handOrderWeight);
        // 新单派单量 =  当日新单派单量 + 改派轮次值 + 昨日倾斜派单量 - 返修奖励轮次
        int distributeNewCount = vo.getDistributeNewCount() + vo.getRedistributeCount() + vo.getYesterdayTiltDistributeCount() - vo.getReworkOtherRewardCount();
        double distributeNewCountRS = this.getDistributeNewCountRecommendScore(distributeNewCount, distributeNewCountWeight);
        // 星级
        double starLevelScoreAvgRS = this.getStarLevelScoreAvgRecommendScore(vo.getStarLevelScore(), starLevelScoreWeight);
        // 服务分
        double serveScoreRS = this.getServeScoreRecommendScore(vo.getCompositeScore(), serveScoreWeight);
        // 单时比
        double datumOrderHourRatioRS = this.getDatumOrderHourRatioRecommendScore(vo.getDatumOrderHourRatio(), datumOrderHourRatioWeight);

        // 计算总的推荐分
        double recommendScore = MathUtil.add(distanceRS, handOrderRS);
        recommendScore = MathUtil.add(recommendScore, distributeNewCountRS);
        recommendScore = MathUtil.add(recommendScore, starLevelScoreAvgRS);
        recommendScore = MathUtil.add(recommendScore, serveScoreRS);
        recommendScore = MathUtil.add(recommendScore, datumOrderHourRatioRS);
        // 减去虚假改派分
        if (NumberUtil.isNotNullOrZero(vo.getFalseRedistributeScore())) {
            recommendScore = MathUtil.sub(recommendScore, MathUtil.mul(vo.getFalseRedistributeScore(), 100D));
        }
        // 减去虚假取消分
        if (NumberUtil.isNotNullOrZero(vo.getFalseCancelScore())) {
            recommendScore = MathUtil.sub(recommendScore, MathUtil.mul(vo.getFalseCancelScore(), 100D));
        }

        return MathUtil.div(recommendScore, 100D, 2);
    }

    /**
     * 距离推荐分
     *
     * @param distance       距离
     * @param distanceWeight 距离权重
     * @return
     */
    private double getDistanceRecommendScore(Double distance, int distanceWeight) {
        if (distance == null || distanceWeight == 0) {
            return 0;
        }

        // 距离权重分值：A≤1KM，分值100，每增加1KM分值减5，不足1KM按1KM计算，如：1.1KM算2KM。权值：分值×权重占比
        // 向上取整
        int intCeil = distance == 0D ? 1 : (int) Math.ceil(distance);
        int score = 100 - ((intCeil - 1) * 5);
        return score > 0 ? MathUtil.mul(score, distanceWeight) : 0;
    }

    /**
     * 新单派单量推荐分
     *
     * @param distributeNewCount       今日成功单
     * @param distributeNewCountWeight 今日成功单权重
     * @return
     */
    private double getDistributeNewCountRecommendScore(int distributeNewCount, int distributeNewCountWeight) {
        if (distributeNewCountWeight == 0) {
            return 0;
        }

        // 新单派单量权重分：满分100分，每派1单，权值分减少：10分×权重占比；最低为0不会负数
        int score = 100 - distributeNewCount * 10;

        return score > 0 ? MathUtil.mul(score, distributeNewCountWeight) : 0;
    }

    /**
     * 手头工单推荐分
     *
     * @param vo
     * @param handOrderWeight 手头单权重
     * @return
     */
    private double getHandOrderRecommendScore(ZsOrderDistributeVO vo, int handOrderWeight) {
        int handOrder = vo.getHandCount();
        int maxHandOrder = vo.getMaxHandCount();

        if (maxHandOrder == 0 || handOrderWeight == 0) {
            return 0;
        }

        // 手头单占比
        double handCountRatio = 100.0D * MathUtil.div(maxHandOrder - handOrder, maxHandOrder, 3);
        vo.setHandCountRatio((int) handCountRatio);

        // 指工程师同品类未完成的订单数(待件&拉修除外
        //手头单分值：100 * (工程师最大手头单 - 手头单) / 工程师最大手头单   × 权重占比
        double intScore = handCountRatio * (double) handOrderWeight;
        return intScore > 0 ? intScore : 0;
    }

    /**
     * 服务分推荐分
     *
     * @param serveScore
     * @param serveScoreWeight
     * @return
     */
    private double getServeScoreRecommendScore(Integer serveScore, int serveScoreWeight) {
        if (serveScoreWeight == 0) {
            return 0;
        }

        /*
        // 80分，为100分，每减1分，分值减1分
        int score = 100;
        int maxValue = 80;

        if (serveScore < maxValue) {
            score -= maxValue - serveScore;
        }
        */

        int score = serveScore;

        return score > 0 ? MathUtil.mul(score, serveScoreWeight) : 0;
    }

    /**
     * 单时比推荐分
     *
     * @param datumOrderHourRatio
     * @param datumOrderHourRatioWeight
     * @return
     */
    private double getDatumOrderHourRatioRecommendScore(Integer datumOrderHourRatio, int datumOrderHourRatioWeight) {
        if (datumOrderHourRatioWeight == 0) {
            return 0;
        }

        // 单时比单位为千分之一，为0满分100分，每增加10 减一分
        int score = 100 - datumOrderHourRatio / 10;

        return score > 0 ? MathUtil.mul(score, datumOrderHourRatioWeight) : 0;
    }

    /**
     * 星级推荐分
     *
     * @param starLevelScore
     * @param starLevelScoreWeight 星级分权重
     * @return
     */
    private double getStarLevelScoreAvgRecommendScore(Double starLevelScore, int starLevelScoreWeight) {
        if (starLevelScore == null || starLevelScore == 0.0D || starLevelScoreWeight == 0) {
            return 0;
        }

        // 转化为整数进行计算
        int intStarLevelScore = starLevelScore.intValue();

        // 星级分值范围：100～1000，大于等于1000，对应指标分数：100分，小于100分，指标分数：0；
        // 每减50分，分值减5分、不足50分按50分计算

        int score = 100;
        int minValue = 100;
        int maxValue = 1000;

        do {
            if (intStarLevelScore >= maxValue) {
                break;
            }

            if (intStarLevelScore < minValue) {
                score = 0;
                break;
            }

            // 转化为50的整数倍
            int m = intStarLevelScore % 50;
            intStarLevelScore -= m;

            score -= ((maxValue - intStarLevelScore) / 50) * 5;
        } while (false);
        return score > 0 ? MathUtil.mul(score, starLevelScoreWeight) : 0;
    }

    //计算推荐分部分结束******************************************************************************************************//

    //排序和过滤方法部分开始******************************************************************************************************//

    /**
     * 基础条件过滤
     */
    private List<ZsOrderDistributeVO> baseDistributeFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit) {
        List<ZsOrderDistributeVO> masterNormalList = Lists.newArrayListWithCapacity(masterList.size());
        List<ZsOrderDistributeVO> masterStockList = Lists.newArrayListWithCapacity(masterList.size());

        // 拆分列表
        this.splitStockMasterList(distributeMasterQuery.getCityId(), masterList, masterNormalList, masterStockList);

        // 分别过滤
        masterNormalList = this.baseNormalFilter(masterNormalList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, supportGridCountLimit);
        masterStockList = this.baseStockFilter(masterStockList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, supportGridCountLimit);

        // 合并结果
        masterList = Lists.newArrayListWithCapacity(masterList.size());
        masterList.addAll(masterNormalList);
        masterList.addAll(masterStockList);

        return masterList;
    }

    /**
     * 基础条件过滤-普通
     */
    private List<ZsOrderDistributeVO> baseNormalFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit) {
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        List<ZsOrderDistributeVO> tempMasterList = Lists.newArrayListWithCapacity(masterList.size());
        boolean checkBindGrid = supportGridCountLimit != null && supportGridCountLimit > 0 && this.needCheckGridBind(distributeMasterQuery);

        for (ZsOrderDistributeVO vo : masterList) {

            // 同时要满足:子公司&手头返修单&返修催单量&最大手头单&满足最大当日手头单&新单派单量<每日新单派单量&拉修待件数量<最大拉修待件数量&平台直派，工程师绑定少于2个副网格，不允许派单（针对非家修匠工程师）
            if ((!distributeMasterQuery.isGridDistribute() || Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId())) &&
                    (maxReworkCount <= 0 || vo.getHandReworkCount() < maxReworkCount) &&
                    (maxReworkReminderCount <= 0 || vo.getReworkReminderCount() < maxReworkReminderCount) &&
                    (vo.getMaxHandCount() > 0 && vo.getHandCount() < vo.getMaxHandCount()) &&
                    !(distributeMasterQuery.getDutyTime() != null && vo.getMaxDayHandNumber() != null && vo.getDatumDoingCount() >= vo.getMaxDayHandNumber()) &&
                    (vo.getDistributeNewCount() < vo.getDailyNewOrders()) &&
                    (vo.getMaxRasshuPpartsNumber() > 0 && vo.getDeliveryAndWaitPartCount() < vo.getMaxRasshuPpartsNumber()) &&
                    (!(checkBindGrid && this.masterNeedCheckGridBind(vo)) || vo.getSlaveGridCount() == null || vo.getSlaveGridCount() >= supportGridCountLimit)) {
                tempMasterList.add(vo);
            }

        }

        return tempMasterList;
    }

    /**
     * 基础条件过滤-动态库存
     */

    private boolean getHasStock(Integer stockType, DistributeMasterQuery distributeMasterQuery) {
        boolean hasStock = false;

        if (distributeMasterQuery.isOnlyOptimalStock()) {
            if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(stockType)) {
                hasStock = true;
            }
        }
        else {
            if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(stockType) || MasterStockTypeEnum.HAVE_STOCK.getCode().equals(stockType)) {
                hasStock = true;
            }
        }

        return hasStock;
    }

    private List<ZsOrderDistributeVO> baseStockFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery,Integer maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit) {
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        List<ZsOrderDistributeVO> tempMasterList = Lists.newArrayListWithCapacity(masterList.size());

        Map<Integer, Integer> masterStockMap = this.getMasterListStockType(masterList, distributeMasterQuery);
        boolean checkBindGrid = supportGridCountLimit != null && supportGridCountLimit > 0 && this.needCheckGridBind(distributeMasterQuery);

        for (ZsOrderDistributeVO vo : masterList) {

            Integer stockType = masterStockMap.get(vo.getMasterId());
            boolean hasStock = this.getHasStock(stockType, distributeMasterQuery);

            vo.setStockType(stockType);

            // 同时要满足:子公司&手头返修单&返修催单量&最大手头单&新单派单量<每日新单派单量&拉修待件数量<最大拉修待件数量&动态库存&动态库存&平台直派，工程师绑定少于2个副网格，不允许派单（针对非家修匠工程师）
            if ((!distributeMasterQuery.isGridDistribute() || Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId())) &&
                    (maxReworkCount <= 0 || vo.getHandReworkCount() < maxReworkCount) &&
                    (maxReworkReminderCount <= 0 || vo.getReworkReminderCount() < maxReworkReminderCount) &&
                    (vo.getMaxHandCount() > 0 && vo.getHandCount() < vo.getMaxHandCount()) &&
                    (vo.getDistributeNewCount() < vo.getDailyNewOrders() &&
                    (vo.getMaxRasshuPpartsNumber() > 0 && vo.getDeliveryAndWaitPartCount() < vo.getMaxRasshuPpartsNumber())) &&
                    hasStock &&
                    (!(checkBindGrid && this.masterNeedCheckGridBind(vo)) || vo.getSlaveGridCount() == null || vo.getSlaveGridCount() >= supportGridCountLimit)) {
                tempMasterList.add(vo);
            }

        }

        return tempMasterList;
    }

    private List<ZsOrderDistributeVO> baseDutyRecommendFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        List<ZsOrderDistributeVO> tempMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {

            // 同时要满足:子公司&最大手头单&新单派单量<每日新单派单量&拉修待件数量<最大拉修待件数量
            if ((!distributeMasterQuery.isGridDistribute() || Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId())) &&
                    (vo.getMaxHandCount() > 0 && vo.getHandCount() < vo.getMaxHandCount()) &&
                    (vo.getDistributeNewCount() < vo.getDailyNewOrders() && (vo.getMaxRasshuPpartsNumber() > 0 && vo.getDeliveryAndWaitPartCount() < vo.getMaxRasshuPpartsNumber()))
                    ) {
                tempMasterList.add(vo);
            }

        }

        return tempMasterList;
    }

    /**
     * 基础条件过滤快照
     */
    private List<ZsOrderDistributeVO> baseDistributeSnapshotFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit, List<ZsOrderDistributeVO> nonDistributeMasterList) {
        List<ZsOrderDistributeVO> masterNormalList = Lists.newArrayListWithCapacity(masterList.size());
        List<ZsOrderDistributeVO> masterStockList = Lists.newArrayListWithCapacity(masterList.size());

        // 拆分列表
        this.splitStockMasterList(distributeMasterQuery.getCityId(), masterList, masterNormalList, masterStockList);

        // 分别过滤
        masterNormalList = this.baseNormalSnapshotFilter(masterNormalList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, supportGridCountLimit, nonDistributeMasterList);
        masterStockList = this.baseStockSnapshotFilter(masterStockList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, supportGridCountLimit, nonDistributeMasterList);

        // 合并结果
        masterList = Lists.newArrayListWithCapacity(masterList.size());
        masterList.addAll(masterNormalList);
        masterList.addAll(masterStockList);

        return masterList;
    }

    /**
     * 基础条件过滤快照-普通
     */
    private List<ZsOrderDistributeVO> baseNormalSnapshotFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit, List<ZsOrderDistributeVO> nonDistributeMasterList) {
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        List<ZsOrderDistributeVO> tempMasterList = Lists.newArrayListWithCapacity(masterList.size());
        boolean checkBindGrid = supportGridCountLimit != null && supportGridCountLimit > 0 && this.needCheckGridBind(distributeMasterQuery);

        for (ZsOrderDistributeVO vo : masterList) {

            vo.setCheckCompanyId(!distributeMasterQuery.isGridDistribute() || Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId()));
            vo.setCheckMaxReworkCount(maxReworkCount <= 0 || vo.getHandReworkCount() < maxReworkCount);
            vo.setCheckMaxReworkReminderCount(maxReworkReminderCount <= 0 || vo.getReworkReminderCount() < maxReworkReminderCount);
            vo.setCheckMaxHandCount(vo.getMaxHandCount() > 0 && vo.getHandCount() < vo.getMaxHandCount());
            vo.setCheckMaxDayHandNumber(!(distributeMasterQuery.getDutyTime() != null && vo.getMaxDayHandNumber() != null && vo.getDatumDoingCount() >= vo.getMaxDayHandNumber()));
            // 今日新单派单量
            int distributeNewCount = vo.getDistributeNewCount();
            // 每日新单派单量
            Integer dailyNewOrders = vo.getDailyNewOrders();
            if(Objects.nonNull(dailyNewOrders) && distributeNewCount < dailyNewOrders.intValue()){
                vo.setCheckDistributeNewCount(Boolean.TRUE);
            }else{
                vo.setCheckDistributeNewCount(Boolean.FALSE);
            }
            vo.setCheckMaxDeliveryAndWaitPartCount(vo.getMaxRasshuPpartsNumber() > 0 && vo.getDeliveryAndWaitPartCount() < vo.getMaxRasshuPpartsNumber());
            vo.setCheckBindGridCount(!(checkBindGrid && this.masterNeedCheckGridBind(vo)) || vo.getSlaveGridCount() == null || vo.getSlaveGridCount() >= supportGridCountLimit);

            // 同时要满足:子公司&手头返修单&返修催单&最大手头单&满足最大当日手头单&新单派单量<每日新单派单量&拉修待件数量<最大拉修待件数量&平台直派，工程师绑定少于2个副网格，不允许派单（针对非家修匠工程师）

            if (vo.getCheckCompanyId() &&
                    vo.getCheckMaxReworkCount() &&
                    vo.getCheckMaxReworkReminderCount() &&
                    vo.getCheckMaxHandCount() &&
                    vo.getCheckMaxDayHandNumber() &&
                    vo.getCheckDistributeNewCount() &&
                    vo.getCheckMaxDeliveryAndWaitPartCount() &&
                    vo.getCheckBindGridCount()) {
                tempMasterList.add(vo);
            }
            else {
                nonDistributeMasterList.add(vo);
            }
        }

        return tempMasterList;
    }

    /**
     * 基础条件过滤快照-动态库存
     */
    private List<ZsOrderDistributeVO> baseStockSnapshotFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit, List<ZsOrderDistributeVO> nonDistributeMasterList) {
        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        List<ZsOrderDistributeVO> tempMasterList = Lists.newArrayListWithCapacity(masterList.size());

        Map<Integer, Integer> masterStockMap = this.getMasterListStockType(masterList, distributeMasterQuery);

        boolean checkBindGrid = supportGridCountLimit != null && supportGridCountLimit > 0 && this.needCheckGridBind(distributeMasterQuery);

        for (ZsOrderDistributeVO vo : masterList) {

            Integer stockType = masterStockMap.get(vo.getMasterId());
            boolean hasStock = this.getHasStock(stockType, distributeMasterQuery);

            vo.setStockType(stockType);
            vo.setCheckCompanyId(!distributeMasterQuery.isGridDistribute() || Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId()));
            vo.setCheckMaxReworkCount(maxReworkCount <= 0 || vo.getHandReworkCount() < maxReworkCount);
            vo.setCheckMaxReworkReminderCount(maxReworkReminderCount <= 0 || vo.getReworkReminderCount() < maxReworkReminderCount);
            vo.setCheckMaxHandCount(vo.getMaxHandCount() > 0 && vo.getHandCount() < vo.getMaxHandCount());
            vo.setCheckDistributeNewCount(vo.getDistributeNewCount() < vo.getDailyNewOrders());
            vo.setCheckMaxDeliveryAndWaitPartCount(vo.getMaxRasshuPpartsNumber() > 0 && vo.getDeliveryAndWaitPartCount() < vo.getMaxRasshuPpartsNumber());
            vo.setCheckStock(hasStock);
            vo.setCheckBindGridCount(!(checkBindGrid && this.masterNeedCheckGridBind(vo)) || vo.getSlaveGridCount() == null || vo.getSlaveGridCount() >= supportGridCountLimit);

            // 同时要满足:子公司&手头返修单&最大手头单&新单派单量<每日新单派单量&拉修待件数量<最大拉修待件数量&动态库存&平台直派，工程师绑定少于2个副网格，不允许派单（针对非家修匠工程师）

            if (vo.getCheckCompanyId() &&
                    vo.getCheckMaxReworkCount() &&
                    vo.getCheckMaxReworkReminderCount() &&
                    vo.getCheckMaxHandCount() &&
                    vo.getCheckDistributeNewCount() &&
                    vo.getCheckMaxDeliveryAndWaitPartCount() &&
                    vo.getCheckStock() &&
                    vo.getCheckBindGridCount()) {
                tempMasterList.add(vo);
            }
            else {
                nonDistributeMasterList.add(vo);
            }
        }

        return tempMasterList;
    }

    /**
     * 校验基础派单原因
     */
    private void checkBaseDistributeReason(ZsOrderDistributeVO vo,
                                           DistributeMasterQuery distributeMasterQuery,
                                           int maxReworkCount, Integer supportGridCountLimit,
                                           int maxReworkReminderCount,
                                           StringJoiner sj) {
        boolean isStock = false;

        // 判断是否城市开通动态库存
        boolean isWhiteCity = orderStockBService.isWhiteWorkCity(distributeMasterQuery.getCityId());
        if (isWhiteCity) {
            isStock = true;
        } else {
            // 获取动态库存工程师ID列表
            Set<Integer> stockMasterIdSet = orderStockBService.getStockMasterIdList();
            if (CollectionUtils.isNotEmpty(stockMasterIdSet) && stockMasterIdSet.contains(vo.getMasterId())) {
                isStock = true;
            }
        }

        // 子公司校验
        if (distributeMasterQuery.isGridDistribute() && !Objects.equals(distributeMasterQuery.getGridCompanyId(), vo.getCompanyId())) {
            sj.add("子公司不匹配");
            //return "子公司不匹配";
        }

        if (isStock) {
            this.checkBaseStockReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj);
            //sj.add(this.checkBaseStockReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj));
            //return this.checkBaseStockReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount);
        }

        this.checkBaseNormalReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj);
        //sj.add(this.checkBaseNormalReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount, sj));
        //return this.checkBaseNormalReason(vo, distributeMasterQuery, maxReworkCount, supportGridCountLimit, maxReworkReminderCount);

        //return sj.toString();
    }

    /**
     * 校验基础派单原因-普通
     */
    private void checkBaseNormalReason(ZsOrderDistributeVO vo,
                                         DistributeMasterQuery distributeMasterQuery,
                                         int maxReworkCount,
                                         Integer supportGridCountLimit,
                                         int maxReworkReminderCount,
                                         StringJoiner sj) {

        // 返修单催单次数
        if (maxReworkReminderCount > 0 && vo.getReworkReminderCount() >= maxReworkReminderCount) {
            sj.add("返修单催单次数超过最大限制次数");
            //return "返修单催单次数超过最大限制次数";
        }

        // 手头返修单
        if (maxReworkCount > 0 && vo.getHandReworkCount() >= maxReworkCount) {
            sj.add("手头返修单超过最大返修单限制");
            //return "手头返修单超过最大返修单限制";
        }

        // 最大手头单
        if (vo.getMaxHandCount() <= 0) {
            sj.add("最大手头单设置为0");
            //return "最大手头单设置为0";
        }

        if (vo.getHandCount() >= vo.getMaxHandCount()) {
            sj.add(String.format("超过最大手头单:%d/%d", vo.getHandCount(), vo.getMaxHandCount()));
            //return String.format("超过最大手头单:%d/%d", vo.getHandCount(), vo.getMaxHandCount());
        }

        // 最大当日手头单(预约时间不为空）
        if (distributeMasterQuery.getDutyTime() != null) {

            // 日手头单
            if (vo.getMaxDayHandNumber() != null) {
                if (vo.getMaxDayHandNumber() <= 0) {
                    sj.add("最大日手头单设置为0");
                    //return "最大日手头单设置为0";
                }

                if (vo.getDatumDoingCount() >= vo.getMaxDayHandNumber()) {
                    sj.add(String.format("超过最大日手头单:%d/%d", vo.getDatumDoingCount(), vo.getMaxDayHandNumber()));
                    //return String.format("超过最大日手头单:%d/%d", vo.getDatumDoingCount(), vo.getMaxDayHandNumber());
                }
            }

        }

        // 新单派单量
        if (vo.getDistributeNewCount() >= vo.getDailyNewOrders()) {
            sj.add(String.format("超过最大每日新单派单量:%d/%d", vo.getDistributeNewCount(), vo.getDailyNewOrders()));
            //return String.format("超过最大每日新单派单量:%d/%d", vo.getDistributeNewCount(), vo.getDailyNewOrders());
        }

        // 拉修待件数量
        if (vo.getMaxRasshuPpartsNumber() <= 0 || vo.getDeliveryAndWaitPartCount() >= vo.getMaxRasshuPpartsNumber()) {
            sj.add(String.format("超过最大拉修待件数量:%d/%d", vo.getDeliveryAndWaitPartCount(), vo.getMaxRasshuPpartsNumber()));
            //return String.format("超过最大拉修待件数量:%d/%d", vo.getDeliveryAndWaitPartCount(), vo.getMaxRasshuPpartsNumber());
        }

        // 平台直派，工程师绑定少于2个副网格，不允许派单（针对非家修匠工程师）
        boolean checkBindGrid = supportGridCountLimit != null && supportGridCountLimit > 0 && this.needCheckGridBind(distributeMasterQuery);

        if (checkBindGrid && this.masterNeedCheckGridBind(vo) && vo.getSlaveGridCount() != null && vo.getSlaveGridCount() < supportGridCountLimit) {
            sj.add(String.format("工程师副网格绑定少于%d个，不可派单", supportGridCountLimit));
            //return String.format("工程师副网格绑定少于%d个，不可派单", supportGridCountLimit);
        }
    }

    /**
     * 校验基础派单原因-动态库存
     */
    private void checkBaseStockReason(ZsOrderDistributeVO vo,
                                        DistributeMasterQuery distributeMasterQuery,
                                        int maxReworkCount,
                                        Integer supportGridCountLimit,
                                        int maxReworkReminderCount,
                                        StringJoiner sj) {

        // 工程师id集合
        List<ZsOrderDistributeVO> masterList = Lists.newArrayList(vo);
        Map<Integer, Integer> masterStockMap = this.getMasterListStockType(masterList, distributeMasterQuery);

        Integer stockType = masterStockMap.get(vo.getMasterId());
        boolean hasStock = this.getHasStock(stockType, distributeMasterQuery);

        // 动态库存
        if (!hasStock) {
            sj.add("当日库存已满");
            //return String.format("当日库存已满");
        }
    }

    //排序和过滤方法部分结束******************************************************************************************************//

    //相关工具方法部分开始******************************************************************************************************//

    // 过滤出只有在服务范围内的师傅
    private List<ZsOrderDistributeVO> scopeStatusFilter(List<ZsOrderDistributeVO> masterList) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO zsOrderDistributeVO : masterList) {

            // 在服务范围内
            if (Objects.equals(GlobalConsts.YES, zsOrderDistributeVO.getScopeStatus())) {
                descMasterList.add(zsOrderDistributeVO);
            }
        }

        return descMasterList;
    }

    private List<ZsOrderDistributeVO> scopeStatusSnapshotFilter(List<ZsOrderDistributeVO> masterList, List<ZsOrderDistributeVO> nonDistributeMasterList) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {

            // 在服务范围内
            if (Objects.equals(GlobalConsts.YES, vo.getScopeStatus())) {
                vo.setCheckServiceScope(true);
                descMasterList.add(vo);
            }
            else {
                vo.setCheckServiceScope(false);
                nonDistributeMasterList.add(vo);
            }
        }

        return descMasterList;
    }

    // 非直营过滤出App在线的师傅
    private List<ZsOrderDistributeVO> onlineStatusFilter(List<ZsOrderDistributeVO> masterList) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO zsOrderDistributeVO : masterList) {

            // 直营或者在线
            if (Objects.equals(zsOrderDistributeVO.getAgent(), GlobalConsts.NO) ||
                    Objects.equals(GlobalConsts.YES, zsOrderDistributeVO.getOnlineStatus())) {
                descMasterList.add(zsOrderDistributeVO);
            }
        }

        return descMasterList;
    }

    private List<ZsOrderDistributeVO> onlineStatusSnapshotFilter(List<ZsOrderDistributeVO> masterList, List<ZsOrderDistributeVO> nonDistributeMasterList) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {

            // 直营或者在线
            if (Objects.equals(vo.getAgent(), GlobalConsts.NO) ||
                    Objects.equals(GlobalConsts.YES, vo.getOnlineStatus())) {
                vo.setCheckAgentOnline(true);
                descMasterList.add(vo);
            }
            else {
                vo.setCheckAgentOnline(false);
                nonDistributeMasterList.add(vo);
            }
        }

        return descMasterList;
    }

    // 按主技能和手头单量排序
    private List<ZsOrderDistributeVO> sortByMainSkillId(List<ZsOrderDistributeVO> masterList, String mainSkillId) {

        Collections.sort(masterList, (item1, item2) -> {

            // 都符合主技能或者都不符合主技能则比较手头单
            if ((mainSkillId.equals(item1.getMainSkillId()) && mainSkillId.equals(item2.getMainSkillId())) ||
                    (!mainSkillId.equals(item1.getMainSkillId()) && !mainSkillId.equals(item2.getMainSkillId()))) {
                return item1.getHandCount() - item2.getHandCount();
            }

            // 其中一个符合主技能优先排序
            return mainSkillId.equals(item1.getMainSkillId()) ? -1 : 1;
        });

        return masterList;
    }

    /**
     * 计算距离 （距离：工程师当前位置，和当前订单的位置距离）
     */
    private void calcMasterOrderDistance(Double longitude, Double latitude, List<ZsOrderDistributeVO> masterList) {
        if (longitude == null || latitude == null || CollectionUtils.isEmpty(masterList)) {
            return;
        }

        if (useNavigationDistance) {
            boolean ret = this.calcMasterOrderNavigationDistance(longitude, latitude, masterList);

            // 调用百度接口失败，使用简单方法计算
            if (!ret) {
                this.calcMasterOrderSimpleDistance(longitude, latitude, masterList);
            } else {
                // 把距离为0的按简单距离再处理一遍
                for (ZsOrderDistributeVO vo : masterList) {
                    if (vo.getDistance() != null && vo.getDistance() == 0.0D) {
                        double dDistance = getCornerDistance(longitude, latitude, vo.getMasterLng(), vo.getMasterLat());
                        double kmDistance = MathUtil.div((int) dDistance, 1000);
                        vo.setDistance(kmDistance);
                    }
                }
            }
        } else {
            this.calcMasterOrderSimpleDistance(longitude, latitude, masterList);
        }
    }

    /**
     * 查询网格外工程师是否是相邻网格
     */
    private void getEngineerAdjoinGrid(OrderDetail orderDetail, List<ZsOrderDistributeVO> masterList) {
        if (NumberUtil.isNullOrZero(orderDetail.getGridId()) || CollectionUtils.isEmpty(masterList)) {
            return;
        }

        List<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
        EngineerAdjoinGridDIO dio = new EngineerAdjoinGridDIO();
        dio.setGridId(orderDetail.getGridId());
        dio.setEngineerIdList(masterIdList);
        logger.info("[{}]查询工程师相邻网格入参：【{}】", orderDetail.getDetailId(), dio);
        ResponseDTO<List<EngineerAdjoinGridDRO>> responseDTO = gridEngineerListRemoteService.listEngineerAdjoinGridByGridIdAndEngineerIdList(dio);
        logger.info("[{}]查询工程师相邻网格出参：【{}】", orderDetail.getDetailId(), responseDTO);
        if (!responseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            return;
        }

        List<EngineerAdjoinGridDRO> list = responseDTO.getData();
        List<Integer> adjoinList = list.stream()
                .filter(e -> Objects.equals(e.getAdjoinGrid(), com.zmn.consts.GlobalConsts.YES))
                .map(EngineerAdjoinGridDRO::getEngineerId).collect(Collectors.toList());
        masterList.forEach(item -> {
            item.setAdjoinGrid(adjoinList.contains(item.getMasterId()));
        });
    }

    /**
     * 计算导航距离 （距离：工程师当前位置，和当前订单的位置距离）
     */
    private boolean calcMasterOrderNavigationDistance(Double longitude, Double latitude, List<ZsOrderDistributeVO> masterList) {
        if (longitude == null || latitude == null || CollectionUtils.isEmpty(masterList)) {
            return true;
        }

        // 订单位置
        Point orderPoint = new Point(longitude, latitude);

        // 工程师位置，有位置信息的工程师才运算
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());
        List<Point> descPointList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {
            Double masterLat = vo.getMasterLat();
            Double masterLng = vo.getMasterLng();

            if (masterLat != null && masterLng != null) {
                descMasterList.add(vo);
                descPointList.add(new Point(masterLng, masterLat));
            }
        }

        // 没有有位置信息的工程师不处理
        if (CollectionUtils.isEmpty(descMasterList)) {
            return true;
        }

        List<Integer> multiNavigationDistance = baiduMapBService.getMultiRidingDistance(orderPoint, descPointList);

        // 调用百度接口失败，返回失败
        if (multiNavigationDistance == null) {
            return false;
        }

        for (int i = 0; i < multiNavigationDistance.size(); i++) {
            Integer mDistance = multiNavigationDistance.get(i);
            double kmDistance = MathUtil.div(mDistance, 1000);
            descMasterList.get(i).setDistance(kmDistance);
        }

        return true;
    }

    /**
     * 计算直线距离 （距离：工程师当前位置，和当前订单的位置距离）
     */
    private void calcMasterOrderSimpleDistance(Double longitude, Double latitude, List<ZsOrderDistributeVO> masterList) {
        if (longitude == null || latitude == null || CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 工程师位置，有位置信息的工程师才运算
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {
            Double masterLat = vo.getMasterLat();
            Double masterLng = vo.getMasterLng();

            if (masterLat != null && masterLng != null && masterLat > 0 && masterLng > 0) {
                descMasterList.add(vo);
            }

        }

        // 没有有位置信息的工程师不处理
        if (CollectionUtils.isEmpty(descMasterList)) {
            return;
        }

        List<Integer> multiSimpleDistance = Lists.newArrayListWithCapacity(descMasterList.size());
        for (ZsOrderDistributeVO vo : descMasterList) {
            double dDistance = getCornerDistance(longitude, latitude, vo.getMasterLng(), vo.getMasterLat());
            multiSimpleDistance.add((int) dDistance);
        }

        for (int i = 0; i < multiSimpleDistance.size(); i++) {
            Integer mDistance = multiSimpleDistance.get(i);
            double kmDistance = MathUtil.div(mDistance, 1000);
            descMasterList.get(i).setDistance(kmDistance);
        }

    }

    // 根据工单信息生成查询对象
    @Override
    public DistributeMasterQuery buildDistributeMasterQuery(OrderWork orderWork, OrderDetail orderDetail, boolean isGridDistribute) {
        DistributeMasterQuery distributeMasterQuery = new DistributeMasterQuery();

        distributeMasterQuery.setPlat(orderWork.getPlatWork());
        distributeMasterQuery.setBizType(orderWork.getBizType());
        distributeMasterQuery.setChannelId(orderWork.getChannelId());
        distributeMasterQuery.setCompanyId(orderWork.getCompanyId());
        distributeMasterQuery.setManageCompanyId(orderWork.getManageCompanyId());
        distributeMasterQuery.setProvinceId(orderDetail.getProvinceId());
        distributeMasterQuery.setCityId(orderWork.getCityId());
        distributeMasterQuery.setCountyId(orderDetail.getCountyId());
        distributeMasterQuery.setStreetSource(orderDetail.getStreetSource());
        distributeMasterQuery.setStreetId(orderDetail.getStreetId());
        distributeMasterQuery.setServCategId(orderWork.getServCategId());
        distributeMasterQuery.setCategId(orderWork.getCategId());
        distributeMasterQuery.setShowCategId(orderWork.getShowCategId());
        distributeMasterQuery.setDutyTime(orderWork.getDutyTime());
        distributeMasterQuery.setLatitude(orderDetail.getLatitude());
        distributeMasterQuery.setLongitude(orderDetail.getLongitude());
        distributeMasterQuery.setTelephone(orderDetail.getTelephone());
        distributeMasterQuery.setTelephone2(orderDetail.getTelephone2());
        distributeMasterQuery.setTelephone3(orderDetail.getTelephone3());
        distributeMasterQuery.setOrderId(orderWork.getOrderId());
        distributeMasterQuery.setWorkId(orderWork.getWorkId());
        distributeMasterQuery.setOrderType(orderWork.getType());
        distributeMasterQuery.setProductGroupId(orderWork.getProductGroupId());
        distributeMasterQuery.setShowProductGroupId(orderWork.getShowProductGroupId());
        distributeMasterQuery.setProductId(orderWork.getProductId());
        distributeMasterQuery.setShowProductId(orderWork.getShowProductId());
        distributeMasterQuery.setServProductGroupId(orderWork.getServProductGroupId());
        distributeMasterQuery.setMainSkillId(orderWork.getServCategId() + "-" + orderWork.getShowCategId());
        distributeMasterQuery.setGridCompanyId(orderDetail.getGridCompanyId());
        distributeMasterQuery.setGridDistribute(isGridDistribute);

        return distributeMasterQuery;
    }

//    /**
//     * 把dubbo返回的派单工程师转换成vo
//     */
//    private ZsOrderDistributeVO transformDistributeObjectDRO2VO(EngDistributeOrderDRO dro) {
//        ZsOrderDistributeVO vo = new ZsOrderDistributeVO();
//
//        vo.setMasterId(dro.getEngineerId());
//        vo.setMasterPhone(dro.getMasterPhone());
//        vo.setMasterName(dro.getMasterName());
//
//        if (dro.getMasterLat() > 0.0D && dro.getMasterLng() > 0.0D) {
//            vo.setMasterLat(dro.getMasterLat());
//            vo.setMasterLng(dro.getMasterLng());
//        }
//
//        vo.setMaxHandCount(dro.getMaxHandNumber() == null ? 0 : dro.getMaxHandNumber());
//        vo.setMaxDayHandNumber(dro.getMaxDayHandNumber());
//        vo.setDailyNewOrders(dro.getDailyNewOrders());
//        vo.setMaxRasshuPpartsNumber(dro.getMaxRasshuPpartsNumber() == null ? 0 : dro.getMaxRasshuPpartsNumber());
//        vo.setSkillServCategoryId(dro.getSkillServCategoryId());
//        vo.setSkillServCategoryName(dro.getSkillServCategoryName());
//        vo.setSkillCategoryId(dro.getSkillCategoryId());
//        vo.setSkillCategoryName(dro.getSkillCategoryName());
//        vo.setAvatarSrc(dro.getAvatarSrc());
//        vo.setMainSkillId(vo.getSkillServCategoryId() + "-" + vo.getSkillCategoryId());
//        vo.setMainSkillName(vo.getSkillServCategoryName() + "-" + vo.getSkillCategoryName());
//        vo.setEngineerStatus(dro.getEngineerStatus());
//        vo.setEngineerStatusName(dro.getEngineerStatusName());
//        vo.setAgent(dro.getAgent());
//        vo.setSpId(dro.getSpId());
//        vo.setSpName(dro.getSpName());
//        vo.setCompanyId(dro.getSubCompanyId());
//        vo.setNovice(dro.getNovice());
//        vo.setNoviceStatus(BooleanUtil.isFalse(dro.getNovice()) ? GlobalConsts.NO : GlobalConsts.YES);
//        vo.setStarLevelScore(Optional.ofNullable(dro.getStarLevelScore()).orElse(0.0D));
//        vo.setChannelExclusive(dro.getChannelExclusive());
//        vo.setStarLevel(dro.getStarLevel());
//        vo.setProductGroupId(dro.getProductGroupId());
//        //vo.setExcellentFlag(dro.getExcellentFlag());
//
//        return vo;
//    }

    private ZsOrderDistributeVO transformDistributeObjectDRO2VO(EngineerDistributeOrderDRO dro) {
        ZsOrderDistributeVO vo = new ZsOrderDistributeVO();

        vo.setMasterId(dro.getEngineerId());
        vo.setMasterPhone(dro.getEngineerPhone());
        vo.setMasterName(dro.getEngineerName());

        if (Objects.nonNull(dro.getLatitude()) && Objects.nonNull(dro.getLongitude()) && dro.getLatitude() > 0.0D && dro.getLongitude() > 0.0D) {
            vo.setMasterLat(dro.getLatitude());
            vo.setMasterLng(dro.getLongitude());
        }

        vo.setMaxHandCount(dro.getMaxReceiveNum() == null ? 0 : dro.getMaxReceiveNum());
        vo.setMaxDayHandNumber(dro.getMaxDayReceiveNum() == null ? 0 : dro.getMaxDayReceiveNum());
        vo.setDailyNewOrders(dro.getDayDistributeNum() == null ? 0 : dro.getDayDistributeNum());
        vo.setMaxRasshuPpartsNumber(dro.getMaxRasshuPartsNum() == null ? 0 : dro.getMaxRasshuPartsNum());
        vo.setSkillServCategoryId(dro.getMainServCategId());
        vo.setSkillServCategoryName(dro.getMainServCategName());
        vo.setSkillCategoryId(dro.getMainCategId());
        vo.setSkillCategoryName(dro.getMainCategName());
        vo.setAvatarSrc(dro.getAvatarSrc());
        vo.setMainSkillId(vo.getSkillServCategoryId() + "-" + vo.getSkillCategoryId());
        vo.setMainSkillName(vo.getSkillServCategoryName() + "-" + vo.getSkillCategoryName());
        vo.setEngineerStatus(Optional.ofNullable(dro.getStopOrderStatus()).orElse(EngineerStopOrderStatusEnum.NORMAL.getCode()));
        vo.setEngineerStatusName(EngineerStopOrderStatusEnum.getEnumByCode(dro.getStopOrderStatus()).getName());
        vo.setOaStatus(dro.getOaStatus());
        vo.setAgent(dro.getCooperationType());
        vo.setSpId(dro.getSpCompanyId());
        vo.setSpName(dro.getSpCompanyName());
        vo.setCompanyId(dro.getSubCompanyId());
        vo.setNovice(Objects.equals(dro.getNoviceLabelStatus(),2) ? Boolean.TRUE : Boolean.FALSE);
        vo.setNoviceStatus(dro.getNoviceLabelStatus() == null ? GlobalConsts.NO : dro.getNoviceLabelStatus());
        vo.setStarLevelScore(Optional.ofNullable(dro.getStarLevelScore()).orElse(0.0D));
        vo.setChannelExclusive(dro.getChannelExclusive());
        vo.setStarLevel(dro.getStarLevel());
        vo.setProductGroupId(dro.getProductGroupId());
        vo.setExcellentFlag(dro.getExcellentFlag());
        vo.setHierarchyLevel(Optional.ofNullable(dro.getHierarchyLevel()).orElse(0));
        vo.setHierarchyLevel(Optional.ofNullable(dro.getHierarchyLevel()).orElse(0));
        return vo;
    }
    /**
     * 是否等待自动派单
     *
     * @param orderWork
     */
    @Override
    public boolean isWaitAutoDistribute(OrderWork orderWork) {

        // 不是进行中或者不是已确认/已分单
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                || !(Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_CONFIRM)
                || Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_ASSIGN))) {
            logger.info("isWaitAutoDistribute：不是进行中或者不是已确认/已分单");
            return false;
        }

        // 没有预约时间
        if (orderWork.getDutyTime() == null) {
            logger.info("isWaitAutoDistribute：没有预约时间");
            return false;
        }

        String key = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, orderWork.getWorkId());
        String value = redisManager.get(key);

        if (StringUtil.isNotBlank(value)) {
            String[] stub = value.split(":");
            if (stub == null || stub.length != 3) {
                return false;
            }

            // 对比预约时间
            Long dutyTimestamp = Long.valueOf(stub[2]);
            if (dutyTimestamp.equals(orderWork.getDutyTime().getTime())) {
                return true;
            }

            logger.info("isWaitAutoDistribute：预约时间不对");
        }

        logger.info("isWaitAutoDistribute：没有存根");
        return false;
    }

    /**
     * 是否天猫差异化派单
     *
     * @param orderWork
     * @return
     */
    @Override
    public boolean isTmallDistribute(OrderWork orderWork) {

        if (Objects.isNull(orderWork.getOrderId())) {
            return false;
        }

        // 天猫订单扩展数据
        OrderTmallExtend orderTmallExtend = orderTmallExtendBService.findOrderTmallExtendByOrderId(orderWork.getOrderId());
        if (Objects.isNull(orderTmallExtend)) {
            return false;
        }

        // 未核销
        boolean notVerification = !Objects.equals(GlobalConsts.YES, orderTmallExtend.getVerification());
        // 天猫渠道
        boolean isTmallChannel = isTmallChannel(orderWork);

        return isTmallChannel && notVerification;
    }

    /**
     * 是否天猫渠道
     *
     * @param orderWork
     * @return
     */
    @Override
    public boolean isTmallChannel(OrderWork orderWork) {
        // 天猫渠道
        boolean isTmallChannel = Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_WYG);
        return isTmallChannel;
    }

    /**
     * 是否特殊服务商
     *
     * @param orderWork
     * @return
     */
    @Override
    public boolean isSpecialSp(OrderWork orderWork) {
        if (CompanyConsts.VIRTUAL_MANAGE_COMPANY_ID_LIST.contains(orderWork.getManageCompanyId())) {
            return true;
        }

        return false;
    }

    /**
     * 获取派单参数
     *
     * @param orderWork
     * @return
     */
    @Override
    public DistributeArgsDRO getDistributeParam(OrderWork orderWork) {
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        if (distributeConfigDRO == null) {
            return null;
        }

        return distributeConfigDRO.getDistributeArgsDRO();
    }

    /**
     * 是否允许派单
     * @param orderId
     * @param workId
     * @return
     */
    private boolean isAllowDistributeOrder(Long orderId, Long workId) {
        logger.info("orderId={},workId={}", orderId, workId);

        TrackWorkQuery query = new TrackWorkQuery();
        query.setOrderId(orderId);
        query.setWorkId(workId);
        query.setNotStatus(TrackConsts.TRACK_STATUS_FINISHED);
        query.setPromoterTypeList(Lists.newArrayList(GlobalConsts.OPERATE_USER_TYPE_USER, GlobalConsts.OPERATE_USER_TYPE_MASTER));
        query.setNotTrackContentId(TrackConsts.TRACK_CONTENT_ID_REMINDER);
        ResponseDTO<Integer> listResponseDTO = trackWorkListRemoteService.countTrackByQuery(query);
        if (listResponseDTO.isSuccess() && listResponseDTO.getData() <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 根据工单信息生成派单视图对象
     *
     * @param orderWork
     * @param orderDetail
     * @return
     */
    @Override
    public DistributeVO buildDistributeVO(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO) {
        return this.buildDistributeVO(orderWork, orderDetail, distributeArgsDRO, false);
    }

    @Override
    public DistributeVO buildDistributeVO(OrderWork orderWork, OrderDetail orderDetail, DistributeArgsDRO distributeArgsDRO, boolean isGridDistribute) {

        // 派单视图对象
        DistributeVO distributeVO = new DistributeVO();

        // 是否允许派单
        distributeVO.setAllowDistributeOrder(isAllowDistributeOrder(orderWork.getOrderId(), orderWork.getWorkId()));

        // 是否返修
        boolean reworkStatus = Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK);

        // 派单业务类型 0.未知 1.C 2.F 3.B 100.特殊
        int distributeBizType = 0;

        // 特殊派单类型 1.特殊服务商 2.天猫差异派单 3.渠道指定派单
        int specialDistributeType = 0;

        // 新单判断是否特殊派单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {

            do {

                // 特殊服务商（ID：42958）
                boolean isSpecialSp = this.isSpecialSp(orderWork);
                if (isSpecialSp) {
                    distributeBizType = OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_SPECIAL;
                    specialDistributeType = OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_SP;
                    break;
                }

                // 是否天猫渠道差异化派单
                boolean isTmallDistribute = this.isTmallDistribute(orderWork);
                if (isTmallDistribute) {
                    distributeBizType = OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_SPECIAL;
                    specialDistributeType = OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_TMALL;
                    break;
                }

            } while (false);

        }

        // 不是特殊派单，按业务类型赋值
        if (distributeBizType == 0) {
            switch (orderWork.getBizType()) {
                case com.zmn.consts.GlobalConsts.BIZ_TYPE_C:
                    distributeBizType = OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C;
                    break;
                case com.zmn.consts.GlobalConsts.BIZ_TYPE_F:
                    distributeBizType = OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F;
                    break;
            }
        }

        // 是否开启简单派单
        boolean simpleStatus = true;
        // 是否开启推荐派单
        boolean recommendStatus = false;
        // 是否开启公平派单
        boolean fairStatus = false;

        if (distributeArgsDRO != null) {

            // 简单派单
            if (!Objects.equals(distributeArgsDRO.getNewSimpleStatus(), GlobalConsts.YES)) {
                simpleStatus = false;
            }

            // 推荐派单
            if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND)) {
                recommendStatus = true;
            }
            // 公平派单
            else if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR)) {
                fairStatus = true;
            }

        }

        // 全部没有，默认只有简单派单
        if (!simpleStatus && !recommendStatus && !fairStatus) {
            simpleStatus = true;
        }

        // 如果没有推荐也没有公平原则，只查基础师傅列表
        if (!recommendStatus && !fairStatus) {
            distributeVO.setOnlyBaseMasterList(true);
        } else {
            distributeVO.setOnlyBaseMasterList(false);
        }

        distributeVO.setReworkStatus(reworkStatus);
        distributeVO.setDistributeBizType(distributeBizType);
        distributeVO.setSpecialDistributeType(specialDistributeType);
        distributeVO.setSimpleStatus(simpleStatus);
        distributeVO.setRecommendStatus(recommendStatus);
        distributeVO.setFairStatus(fairStatus);

        distributeVO.setOrderId(orderWork.getOrderId());
        distributeVO.setWorkId(orderWork.getWorkId());
        distributeVO.setDutyInfo(String.format("%s - %s", DateUtil.getDateTimeStr(orderWork.getDutyTime()), orderDetail.getProductInfo()));
        distributeVO.setLatitude(orderDetail.getLatitude());
        distributeVO.setLongitude(orderDetail.getLongitude());
        distributeVO.setGridId(orderDetail.getGridId());
        distributeVO.setMasterId(orderWork.getMasterId());
        distributeVO.setMasterName(orderWork.getMasterName());
        distributeVO.setProductGroupId(orderDetail.getProductGroupId());
        distributeVO.setProductGroupName(orderDetail.getProductGroupName());
        distributeVO.setMainSkillId(orderWork.getServCategId() + "-" + orderWork.getShowCategId());

        // 天猫勤鸽店走差异化派单流程
        if (distributeBizType == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_SPECIAL && specialDistributeType == OrderDistributeConsts.SPECIAL_DISTRIBUTE_TYPE_TMALL) {
            // 天猫订单扩展数据
            OrderTmallExtend orderTmallExtend = orderTmallExtendBService.findOrderTmallExtendByOrderId(orderWork.getOrderId());

            if (Objects.nonNull(orderTmallExtend) && StringUtils.isNotBlank(orderTmallExtend.getServiceCode())) {
                distributeVO.setServiceCodeName(OrderConsts.getTmallServiceCodeName(orderTmallExtend.getServiceCode()));
            } else {
                distributeVO.setServiceCodeName("其他");
            }

            if (Objects.nonNull(orderTmallExtend) && Objects.equals(orderTmallExtend.getVipOrder(), GlobalConsts.YES)) {
                distributeVO.setVipOrder(GlobalConsts.YES);
            } else {
                distributeVO.setVipOrder(GlobalConsts.NO);
            }

            if (Objects.nonNull(orderTmallExtend) && Objects.equals(orderTmallExtend.getBigPromotionOrder(), GlobalConsts.YES)) {
                distributeVO.setBigPromotionOrder(GlobalConsts.YES);
            } else {
                distributeVO.setBigPromotionOrder(GlobalConsts.NO);
            }
        }

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(orderWork.getShowProductId());
        ResponseDTO<List<ProductBaseDRO>> responseDTO = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        if (responseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
            ProductBaseDRO baseDRO = responseDTO.getData().get(0);
            distributeVO.setMainSkillName(baseDRO.getServCategName() + "-" + baseDRO.getCategName());
        }

        // 如果是推荐派单和公平派单则查询网格信息
        if (isGridDistribute && (recommendStatus || fairStatus)){
            CircleRangeDIO dio = new CircleRangeDIO();
            dio.setLng(orderDetail.getLongitude());
            dio.setLat(orderDetail.getLatitude());
            // 圆形，范围半径5000米
            dio.setRadius(5000);
            logger.info("获取网格信息入参:[{}]", JSON.toJSONString(dio));
            ResponseDTO<List<GridBaseDRO>> listResponseDTO = gridListRemoteService.listIntersectsGridByLngAndLatAndRadius(dio);
            logger.info("获取网格信息出参:[{}]", JSON.toJSONString(listResponseDTO));
            if (listResponseDTO.isSuccess() && Objects.nonNull(listResponseDTO.getData())){
                List<GridVO> list = Lists.newArrayListWithCapacity(listResponseDTO.getData().size());
                listResponseDTO.getData().forEach(dro -> {
                    GridVO vo = new GridVO();
                    vo.setGridId(dro.getGridId());
                    vo.setGridBaidu(dro.getGridBaidu());
                    vo.setGridName(dro.getGridName());
                    list.add(vo);
                });
                distributeVO.setGridList(list);
            }
        }

        return distributeVO;
    }

    /**
     * 根据工单id和时间戳获取抢单快照
     * @param workId
     * @param snapshotId
     * @return
     */
    @Override
    public DistributeSnapshotVO buildDistributeSnapshotVO(Long workId, Long snapshotId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("workId").is(workId).and("snapshotId").is(snapshotId));
        DistributeSnapshot distributeSnapshot = mongoTemplate.findOne(query, DistributeSnapshot.class,
                MongodbConsts.OMS_ORDER_DISTRIBUTE_SNAPSHOT);
        DistributeSnapshotVO vo = BeanMapper.map(distributeSnapshot, DistributeSnapshotVO.class);
        return vo;
    }

    /**
     * 队列定时派单消费
     *
     * @param parseObject
     * @return
     */
    @Override
    public void distributeConsume(MqWaitDistributeDTO parseObject) {

        // 获取存根
        String key = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, parseObject.getWorkId());
        String value = redisManager.get(key);

        if (StringUtil.isBlank(value)) {
            return;
        }

        // 删除存根
        redisManager.del(key);

        // 对比时戳
        String[] stub = value.split(":");
        if (stub == null || stub.length != 3) {
            return;
        }

        Long timestamp = Long.valueOf(stub[1]);
        if (!timestamp.equals(parseObject.getTimestamp())) {
            return;
        }

        Long dutyTimestamp = Long.valueOf(stub[2]);
        if (!dutyTimestamp.equals(parseObject.getDutyTimestamp())) {
            return;
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(parseObject.getOrderId(), parseObject.getWorkId());
        if (orderWork == null) {
            return;
        }

        // 不是进行中或者不是已确认/分单不处理
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                || (!Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_CONFIRM)
                && !Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_ASSIGN))) {
            return;
        }

        // 没有预约时间或者预约时间不匹配不处理
        if (orderWork.getDutyTime() == null || parseObject.getDutyTimestamp() != orderWork.getDutyTime().getTime()) {
            return;
        }

        try {
            // 调用自动派单
            this.autoDistribute(orderWork, parseObject.getMasterId(), parseObject.getAutoDistributeCount());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    // 删除自动派单存根
    private void delAutoDistributeStub(Long workId) {
        String key = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, workId);
        redisManager.del(key);
    }

    /**
     * 发送至定时自动派单队列
     */
    private boolean sendWaitDistribute(OrderWork orderWork,
                                       Integer masterId,
                                       String autoTimeStart,
                                       int intCurTime,
                                       int intEndTime,
                                       int autoDistributeCount,
                                       Integer nonDistributeRule) {

        // 没有预约时间不处理
        if (orderWork.getDutyTime() == null) {
            return false;
        }

        // 不是新单不处理
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return false;
        }

        // 计次>1不处理
        if (autoDistributeCount > 1) {
            return false;
        }

        // 当前时戳
        Date dateNow = new Date();
        long timestamp = dateNow.getTime();

        // 计算再次自动派单的时间
        Date dateStart = dateNow;
        if (intCurTime > intEndTime) {
            // 如果当前时间超过截止时间，就设置为明天
            dateStart = DateUtil.addDays(dateNow, 1);
        }

        Calendar calendarTimeStart = Calendar.getInstance();
        calendarTimeStart.setTime(dateStart);

        // 随机打散到0~59秒
        long randomSecond = timestamp % 60;

        dateStart = DateUtil.parse(String.format("%d-%d-%d %s:%d", calendarTimeStart.get(Calendar.YEAR), calendarTimeStart.get(Calendar.MONTH) + 1,
                calendarTimeStart.get(Calendar.DAY_OF_MONTH), autoTimeStart, randomSecond), DateUtil.FORMAT_DEFAULT);
        long startDeliverTime = dateStart.getTime();

        // redis保存存根，执行数次:当前时戳:预约时间->作为存根同时保存在redis和mq
        String keyRedis = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, orderWork.getWorkId());
        // 过期时间+1天=86400秒
        int outTimeRedis = (int) ((startDeliverTime - timestamp) / 1000L) + 86400;
        String valueRedis = String.format("%d:%d:%d", autoDistributeCount, timestamp, orderWork.getDutyTime().getTime());
        redisManager.setex(keyRedis, valueRedis, outTimeRedis);

        // 派单队列数据
        MqWaitDistributeDTO distributeDTO = new MqWaitDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(masterId);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        distributeDTO.setDutyTimestamp(orderWork.getDutyTime().getTime());
        distributeDTO.setTimestamp(timestamp);

        // 发送至定时队列
        String keyMQ = "oms_distribute_" + distributeDTO.getOrderId();
        zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, OmsMqTagConsts.ZMN_TOPIC_OMS_WAIT_DISTRIBUTE, keyMQ, JSON.toJSONString(distributeDTO), startDeliverTime);

        // 保存日志
        Date procDate = new Date(startDeliverTime);
        OrderLog orderLog = new OrderLog();

        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        if (NumberUtil.isNotNullOrZero(nonDistributeRule)) {
            orderLog.setContent(String.format("%s-%s", OrderDistributeConsts.getNonDistributeRuleName(nonDistributeRule), DateUtil.toString(procDate, "MM月dd日HH时mm分再次自动派单")));
        }else {
            orderLog.setContent(DateUtil.toString(procDate, "MM月dd日HH时mm分再次自动派单"));
        }

        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_WAIT_DISTRIBUTE);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_WAIT_DISTRIBUTE));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));

        OrderWorkLogUtils.processOrderLogOperater(orderLog, null);

        orderLogBService.save(orderLog);

        return true;
    }

    /**
     * 发送至定时自动派单队列
     */
    private boolean sendAcrossWaitDistribute(OrderWork orderWork, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {

        // 跨网格次数redis，如果跨网格时间等待过后，当前工单当天不再等待
        String acrossCountKey = String.format(RedisKeyConsts.ACROSS_DISTRIBUTE_WAIT_COUNT_ORDER, orderWork.getWorkId());
        String acrossCountValue = redisManager.get(acrossCountKey);
        if (StringUtil.isNotBlank(acrossCountValue)) {
            logger.info("[{}]今天已跨网格等待过，不再等待", orderWork.getWorkId());
            return false;
        }

        // 当前时戳
        Date dateNow = new Date();
        long timestamp = dateNow.getTime();

        // 如果在等待跨网格派单过程中，又进来直接出去
        String acrossRedisKey = String.format(RedisKeyConsts.ACROSS_DISTRIBUTE_WAIT_TIME_ORDER, orderWork.getWorkId());
        String acrossRedisValue = redisManager.get(acrossRedisKey);
        if (StringUtil.isNotBlank(acrossRedisValue)) {
            logger.info("[{}]当天订单在跨网格等待中:[{}]", orderWork.getWorkId(), acrossRedisValue);
            Long acrossValue = Long.parseLong(acrossRedisValue);
            boolean end = (acrossValue - timestamp / 1000L) < 60;
            if (end) {
                return false;
            } else {
                return true;
            }
        }

        int autoDistributeCount = 1;

        // 跨网格等待再次派单时间
        long againDistributeTime = timestamp + distributeArgsDRO.getAcrossDistributeWaitTime() * 60 * 1000;
        String endTime = distributeArgsDRO.getAutoTimeEnd();
        String[] strEndTime = endTime.split(":");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(strEndTime[0]));
        calendar.set(Calendar.MINUTE, Integer.parseInt(strEndTime[1]));
        long autoEndTime = calendar.getTimeInMillis();

        // 如果跨网格等待时长大于最晚派单时间
        if (againDistributeTime >= autoEndTime) {
            // 第二天开始派单重新走一遍
            int intEndTime = Integer.valueOf(strEndTime[0]) * 100 + Integer.valueOf(strEndTime[1]);
            this.sendWaitDistribute(orderWork, null, distributeArgsDRO.getAutoTimeStart(), intEndTime + 1, intEndTime, autoDistributeCount, 0);
        } else {

            // 跨网格派单redis，用来判断是否跨网格等待中，如果存在，则不能手动派单网格外工程师
            int acrossOutTime =  distributeArgsDRO.getAcrossDistributeWaitTime() * 60 + OrderDistributeConsts.ACROSS_DISTRIBUTE_WAIT_TIME;
            acrossRedisValue = String.valueOf(timestamp / 1000L + acrossOutTime);
            redisManager.setex(acrossRedisKey, acrossRedisValue, acrossOutTime);

            long startDeliverTime = timestamp + distributeArgsDRO.getAcrossDistributeWaitTime() * 60 * 1000;

            // redis保存存根，执行数次:当前时戳:预约时间->作为存根同时保存在redis和mq
            String keyRedis = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, orderWork.getWorkId());
            // 过期时间+1天=86400秒
            int outTimeRedis = (int) (timestamp / 1000L) + acrossOutTime + 86400;
            String valueRedis = String.format("%d:%d:%d", autoDistributeCount, timestamp, orderWork.getDutyTime().getTime());
            redisManager.setex(keyRedis, valueRedis, outTimeRedis);

            // 派单队列数据
            MqWaitDistributeDTO distributeDTO = new MqWaitDistributeDTO();
            distributeDTO.setOrderId(orderWork.getOrderId());
            distributeDTO.setWorkId(orderWork.getWorkId());
            distributeDTO.setAutoDistributeCount(autoDistributeCount);
            distributeDTO.setDutyTimestamp(orderWork.getDutyTime().getTime());
            distributeDTO.setTimestamp(timestamp);

            // 修改订单备注
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderWork.getOrderId());
            updateOrderWork.setWorkId(orderWork.getWorkId());
            updateOrderWork.setCurrentRemark(String.format("系统跨网格派单等待%s分钟", distributeArgsDRO.getAcrossDistributeWaitTime()));
            updateOrderWork.setUpdater("系统");
            orderWorkService.updateOrderWorkByKeyForSync(updateOrderWork);

            // 发送至定时队列
            String keyMQ = "oms_distribute_" + distributeDTO.getOrderId();
            zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, OmsMqTagConsts.ZMN_TOPIC_OMS_WAIT_DISTRIBUTE, keyMQ, JSON.toJSONString(distributeDTO), startDeliverTime);

            // 保存日志
            Date procDate = new Date(startDeliverTime);
            String content = String.format("系统跨网格派单等待（%s分钟） - %s", distributeArgsDRO.getAcrossDistributeWaitTime(), DateUtil.toString(procDate, "MM月dd日HH时mm分再次自动派单"));
            this.saveOrderLog(orderWork, dateNow, OrderLogConsts.ORDER_LOG_TYPE_ACROSS_DISTRIBUTE_WAIT_TIME_CODE, content);

        }
        return true;
    }

    /**
     * 保存不能自动派单原因
     * @param distributeVO
     * @param orderWork
     * @param date
     * @param message
     */
    @Override
    public void saveNonDistributeOrderLog(DistributeVO distributeVO, OrderWork orderWork, Date date, String message) {

        String content = null;
        if (Objects.isNull(distributeVO)) {
            content = message;
        } else {
            if (distributeVO.getDistributeRule() != null && distributeVO.getDistributeRule() < 0) {
                content = OrderDistributeConsts.getNonDistributeRuleName(distributeVO.getDistributeRule());
                if (CollectionUtil.isNotNullOrEmpty(distributeVO.getNonDistributeMasterList())) {
                    content += "<a name='distributeSnapshot' style='color: blue;cursor: pointer;'>详情</a>";
                }
            } else {
                content = "未找到满足工程师 <a name='distributeSnapshot' style='color: blue;cursor: pointer;'>详情</a>";
            }
        }

        this.saveOrderLog(orderWork, date, OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_SNAPSHOT, content);

        // 保存日志
        /*OrderLog orderLog = new OrderLog();

        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        if (Objects.isNull(distributeVO)) {
            orderLog.setContent(message);
        } else {
            if (distributeVO.getDistributeRule() != null && distributeVO.getDistributeRule() < 0) {
                orderLog.setContent(OrderDistributeConsts.getNonDistributeRuleName(distributeVO.getDistributeRule()));
            } else {
                orderLog.setContent("未找到满足工程师 <a name='distributeSnapshot' style='color: blue;cursor: pointer;'>详情</a>");
            }
        }

        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_SNAPSHOT);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_SNAPSHOT));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setCreateTime(Optional.ofNullable(date).orElse(new Date()));

        OrderWorkLogUtils.processOrderLogOperater(orderLog, null);

        orderLogBService.save(orderLog);*/
    }

    /**
     * 保存操作日志
     * @param orderWork
     * @param date
     * @param logType
     * @param content
     */
    private void saveOrderLog(OrderWork orderWork, Date date, Integer logType, String content) {
        // 保存日志
        OrderLog orderLog = new OrderLog();

        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setContent(content);
        orderLog.setType(logType);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(logType));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setCreateTime(Optional.ofNullable(date).orElse(new Date()));

        OrderWorkLogUtils.processOrderLogOperater(orderLog, null);

        orderLogBService.save(orderLog);
    }

    /**
     * 发送简单定时自动派单队列
     * 处理派单并发使用
     */
    /*
    private void sendSimpleWaitDistribute(OrderWork orderWork, int autoDistributeCount) {

        // 当前时戳
        long timestamp = System.currentTimeMillis();
        // 5秒后重新执行
        long startDeliverTime = timestamp + 5000;

        // redis保存存根，执行数次:当前时戳:预约时间->作为存根同时保存在redis和mq
        String keyRedis = String.format(RedisKeyConsts.WAIT_AUTO_DISTRIBUTE_ORDER, orderWork.getWorkId());
        // 过期时间+1天=86400秒
        int outTimeRedis = (int) ((startDeliverTime - timestamp) / 1000L) + 86400;
        String valueRedis = String.format("%d:%d:%d", autoDistributeCount, timestamp, orderWork.getDutyTime().getTime());
        redisManager.setex(keyRedis, valueRedis, outTimeRedis);

        // 派单队列数据
        MqWaitDistributeDTO distributeDTO = new MqWaitDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        distributeDTO.setDutyTimestamp(orderWork.getDutyTime().getTime());
        distributeDTO.setTimestamp(timestamp);

        // 发送至定时队列
        String keyMQ = "oms_distribute_" + distributeDTO.getOrderId();
        zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, OmsMqTagConsts.ZMN_TOPIC_OMS_WAIT_DISTRIBUTE, keyMQ, JSON.toJSONString(distributeDTO), startDeliverTime);

        // 保存日志
        Date procDate = new Date(startDeliverTime);
        OrderLog orderLog = new OrderLog();

        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setContent(DateUtil.toString(procDate, "MM月dd日HH时mm分ss秒再次自动派单"));

        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_WAIT_DISTRIBUTE);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_WAIT_DISTRIBUTE));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));

        OrderWorkLogUtils.processOrderLogOperater(orderLog, null);

        orderLogBService.save(orderLog);
    }
    */

    // 相关工具方法部分结束
    // ****************************************************************************************************** //

    /**
     * 创建OMS技能列表
     *
     * @param productId
     * @param showProductId
     * @param servCategId
     * @param categId
     * @return
     */
    private List<DistributeOrderSkillQuery> buildSkillList(Integer productId, Integer showProductId, Integer servCategId, Integer categId) {
        List<DistributeOrderSkillQuery> skillList = new ArrayList<>();

        // 后台产品和二级分类都不为空
        if (productId != null && productId != 0 && categId != null && categId != 0) {
            logger.info("buildSkillList:后台产品和二级分类都不为空");
            DistributeOrderSkillQuery  skillQuery = new DistributeOrderSkillQuery();
            skillQuery.setServCategId(servCategId);
            skillQuery.setCategId(categId);
            skillList.add(skillQuery);

            return skillList;
        }

        // 后台产品和二级分类为空，通过前台产品查询后台产品和二级分类
        ResponseDTO<List<ClassifyDRO>> responseDTO = productForeignListRemoteService.listClassifyByProductId(showProductId);
        logger.info("listAssSimpleCategByShowProductId:" + responseDTO);
        if (responseDTO.isSuccess() && CollectionUtils.isNotEmpty(responseDTO.getData())) {
            List<ClassifyDRO> responseList = responseDTO.getData();

            for (ClassifyDRO dro : responseList) {
                DistributeOrderSkillQuery  skillQuery = new DistributeOrderSkillQuery();
                skillQuery.setServCategId(dro.getServCategId());
                skillQuery.setCategId(dro.getCategId());
                skillList.add(skillQuery);
            }
        } else {
            // 通过前台产品获取后台技能失败，用工单的填充
            logger.info("buildSkillList:通过前台产品获取后台技能失败，用工单的填充");
            DistributeOrderSkillQuery  skillQuery = new DistributeOrderSkillQuery();
            skillQuery.setServCategId(servCategId);
            skillQuery.setCategId(categId);
            skillList.add(skillQuery);
        }

        return skillList;
    }

    /**
     * 创建工程师接口技能列表
     *
     * @param productId
     * @param showProductId
     * @param servCategId
     * @param categId
     * @return
     */
    @Override
    public List<List<DistributeOrderSkillQuery>> buildSkillQueryLists(Integer productId, Integer showProductId, Integer servCategId, Integer categId) {
        List<DistributeOrderSkillQuery > skillList = this.buildSkillList(productId, showProductId, servCategId, categId);

        List<List<DistributeOrderSkillQuery>> skillLists = new ArrayList<>(1);
        skillLists.add(skillList);

        return skillLists;
    }

    /** 网格化派单 **************************************************/

    /**
     * 获取派单配置
     */
    @Override
    public DistributeConfigDRO getDistributeConfig(OrderWork orderWork) {
        // 调用获取派单参数dubbo
        Integer manageCompanyId = Optional.ofNullable(orderWork.getManageCompanyId()).orElse(0);

        DistributeWeightQuery distributeWeightQuery = new DistributeWeightQuery();
        Integer plat = NumberUtil.isNotNullOrZero(orderWork.getPlatWork()) ? orderWork.getPlatWork() : orderWork.getPlat();
        distributeWeightQuery.setPlat(plat);
        distributeWeightQuery.setCompanyId(manageCompanyId);
        distributeWeightQuery.setCityId(orderWork.getCityId());
        distributeWeightQuery.setBizType(orderWork.getBizType());
        distributeWeightQuery.setProductGroupId(orderWork.getServProductGroupId());

        DistributeConfigDRO distributeConfigDRO = distributeWeightListBService.findDistributeConfig(distributeWeightQuery);

        if (distributeConfigDRO == null) {
            logger.info("获取派单配置失败");
            return null;
        }

        return distributeConfigDRO;
    }

    public DistributeConfigDRO getDistributeConfig(DistributeMasterQuery distributeMasterQuery) {
        // 调用获取派单参数dubbo
        Integer manageCompanyId = 0;

        DistributeWeightQuery distributeWeightQuery = new DistributeWeightQuery();
        distributeWeightQuery.setPlat(distributeMasterQuery.getPlat());
        distributeWeightQuery.setCompanyId(manageCompanyId);
        distributeWeightQuery.setCityId(distributeMasterQuery.getCityId());
        distributeWeightQuery.setBizType(distributeMasterQuery.getBizType());
        distributeWeightQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());

        DistributeConfigDRO distributeConfigDRO = distributeWeightListBService.findDistributeConfig(distributeWeightQuery);

        if (distributeConfigDRO == null) {
            logger.info("获取派单配置失败");
            return null;
        }

        return distributeConfigDRO;
    }

    /**
     * 是否特殊派单
     */
    public boolean isSpecialDistribute(OrderWork orderWork) {

        // 非新单不是特殊派单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            logger.info("非新单不是特殊派单");
            return false;
        }

        // 特殊服务商（ID：42958）
        boolean isSpecialSp = this.isSpecialSp(orderWork);
        if (isSpecialSp) {
            logger.info("特殊服务商");
            return true;
        }

        // 是否天猫渠道差异化派单
        boolean isTmallDistribute = this.isTmallDistribute(orderWork);
        if (isTmallDistribute) {
            logger.info("天猫渠道差异化派单");
            return true;
        }

        // 是否渠道指定工程师
//        boolean isChannelDistribute = this.isChannelDistribute(orderWork);
//        if (isChannelDistribute) {
//            logger.info("渠道指定工程师");
//            return true;
//        }

        logger.info("不是特殊派单");
        return false;
    }

    /**
     * 是否平台直派
     */
    @Override
    public boolean isGridDistribute(OrderWork orderWork) {
        if (Objects.equals(orderWork.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            return true;
        }

        return false;
    }

    /**
     * 通过派单参数判断是否网格化派单
     */
    @Override
    public boolean isGridDistributeByConfig(OrderWork orderWork) {

        // 通过派单参数判断
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);

        return this.isGridDistributeByConfig(distributeConfigDRO);
    }

    /**
     * 通过派单参数判断是否网格化派单
     */
    @Override
    public boolean isGridDistributeByConfig(DistributeConfigDRO distributeConfigDRO) {
        if (distributeConfigDRO == null) {
            logger.info("派单参数为空不是网格化派单");
            return false;
        }

        if (Objects.equals(distributeConfigDRO.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            logger.info("派单参数是网格化派单");
            return true;
        }

        logger.info("其他不是网格化派单");
        return false;
    }

    /**
     * 网格化自动派单
     */
    private boolean gridAutoDistribute(OrderWork orderWork, Integer masterId, int autoDistributeCount, DistributeConfigDRO distributeConfigDRO, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("网格化自动派单:workId=" + orderWork.getWorkId());

        // 获取派单参数
        if (distributeConfigDRO == null || distributeConfigDRO.getPlatDirectlyDistributeArgsDRO() == null) {
            // 获取派单参数失败，不自动派单，结束
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
            return false;
        }

        // 自动派单操作计次+1
        autoDistributeCount++;

        // 删除自动派单存根
        // 暂时删除，因为跨网格等待中，如果有修改导致自动派单会将存根删掉，导致前一次等待到时间无法派单
        //this.delAutoDistributeStub(orderWork.getWorkId());

        // 1.统一判断逻辑

        // 1.1 不是进行中的单不处理
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_STATUS);
            return false;
        }

        // 1.2 非已确认的状态不处理
        if (!Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_CONFIRM)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_STATUS);
            return false;
        }

        // 1.3 挂起状态，不自动派单
        if (Objects.equals(orderWork.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SUSPEND);
            return false;
        }

        // 1.4 工单设置为不自动派单
        if (Objects.equals(orderWork.getAutoDistribute(), GlobalConsts.NO)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            return false;
        }

        // 订单详情
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        // 工单联系人姓名不规范，不自动派单
        if (StringUtils.isBlank(orderDetail.getContactName())) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_USER_INFO);
            return false;
        }

        // 2.以下按业务类型区分处理

        // 2.1 C端订单没有预约时间，不自动派单
        if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            if (orderWork.getDutyTime() == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_DUTY_TIME);
                return false;
            }
        }

        // 不是师傅加单，判断自动派单参数
        if (masterId == null) {
            switch (orderWork.getType()) {
                case OrderConsts.ORDER_TYPE_NEW: // 新单

                    // 没有配置新单自动派单，结束
                    if (distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoStatusNew() == null
                            || Objects.equals(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)) {
                        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
                        return false;
                    }

                    break;

                case OrderConsts.ORDER_TYPE_REWORK: // 返修单

                    // 没有配置返修单自动派单，结束
                    if (!Objects.equals(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoStatusRework(), GlobalConsts.YES)) {
                        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
                        return false;
                    }

                    break;

                default:
                    return false;
            }
        }

        // 默认自动派单起止时间
        String autoTimeStart = "7:30";
        String autoTimeEnd = "21:30";

        if (StringUtils.isNotBlank(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeStart()) && StringUtils.isNotBlank(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeEnd())) {
            autoTimeStart = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeStart();
            autoTimeEnd = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeEnd();
        }

        // 不在可派单时间范围内，不自动派单，师傅加单不受约束

        if (masterId == null) {
            Date curTime = DateUtil.getNow();
            int intCurTime = curTime.getHours() * 100 + curTime.getMinutes();

            String[] strStartTime = autoTimeStart.split(":");
            int intStartTime = Integer.valueOf(strStartTime[0]) * 100 + Integer.valueOf(strStartTime[1]);

            String[] strEndTime = autoTimeEnd.split(":");
            int intEndTime = Integer.valueOf(strEndTime[0]) * 100 + Integer.valueOf(strEndTime[1]);

            //logger.info("autoDistribute:intCurTime=" + intCurTime + ",intStartTime=" + intStartTime + "intEndTime=" + intEndTime);
            if (intCurTime < intStartTime || intCurTime > intEndTime) {
                logger.info("gridAutoDistribute:workId=" + orderWork.getWorkId() + ",不在可派单时间范围内，不自动派单:" + distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeStart() + "~" + distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeEnd());
                // 发送至定时自动派单队列
                boolean ret = this.sendWaitDistribute(orderWork, null, autoTimeStart, intCurTime, intEndTime, autoDistributeCount, OrderDistributeConsts.DISTRIBUTE_RULE_REASON_WORK_TIME);
                if (!ret) {
                    distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_WORK_TIME);
                }

                return false;
            }
        }

        // 分类型处理自动派单

        boolean res = false;

        switch (orderWork.getType()) {
            case OrderConsts.ORDER_TYPE_NEW:

                // 新单

                // 师傅加单：有指定派单工程师，先走指定自动派单
                if (masterId != null && masterId > 0) {
                    if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
                        res = this.gridNewOrderAutoDistribute2MasterTypeC(orderWork, orderDetail, masterId, distributeConfigDRO, autoDistributeCount, distributeSnapshotVO);

                        // 如果指定工程师派单成功，结束
                        if (res) {
                            break;
                        }

                        // 保存师傅加单派单失败快照
                        long time = distributeSnapshotVO.getAutoDistributeTime().getTime() - 1;
                        Date date = new Date(time);
                        // 不能自动派单有师傅列表
                        if (CollectionUtils.isNotEmpty(distributeSnapshotVO.getNonDistributeMasterList())) {
                            ZsOrderDistributeVO vo = distributeSnapshotVO.getNonDistributeMasterList().get(0);
                            distributeSnapshotVO.setDistributeFailReason(this.getMasterNonDistributeReason(vo));
                            // 保存日志
                            this.saveNonDistributeOrderLog(null, orderWork, date, distributeSnapshotVO.getDistributeFailReason());
                        } else {
                            this.saveNonDistributeOrderLog(null, orderWork, date, distributeSnapshotVO.getDistributeFailReason());
                        }
                    }
                }

                if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
                    res = this.gridNewOrderAutoDistributeTypeC(orderWork, orderDetail, distributeConfigDRO, autoDistributeCount, distributeSnapshotVO);
                }

                break;

            case OrderConsts.ORDER_TYPE_REWORK:

                // 返修单
//                res = this.reworkOrderAutoDistribute(orderWork, orderDetail, distributeConfigDRO.getPlatDirectlyDistributeArgsDRO(), autoDistributeCount, OrderDistributeConsts.DISTRIBUTE_WAY_PLAT, distributeSnapshotVO);
                // 平台直派-返修源工程师自动派单
                res = this.gridReworkOrderOriginalMasterAutoDistribute(orderWork, orderDetail, distributeConfigDRO.getPlatDirectlyDistributeArgsDRO(), autoDistributeCount, OrderDistributeConsts.DISTRIBUTE_WAY_PLAT, distributeSnapshotVO);

                // 如果源工程师派单成功，结束
                if (res) {
                    break;
                }

                // 保存源工程师派单失败快照
//                long time = distributeSnapshotVO.getAutoDistributeTime().getTime() - 1;
//                this.saveNonDistributeOrderLog(null, orderWork, new Date(time), distributeSnapshotVO.getDistributeFailReason());

                // 返修公平派单
                res = this.gridReworkOrderAutoDistribute(orderWork, orderDetail, distributeConfigDRO, autoDistributeCount, distributeSnapshotVO);
                break;

            default:
                break;
        }

        return res;
    }

    /**
     * 获取师傅不能派单原因
     * @param vo
     * @return
     */
    private String getMasterNonDistributeReason(ZsOrderDistributeVO vo) {
        String reason = "加单工程师不满足，原因：";
        StringJoiner sj = new StringJoiner("，");
        if (BooleanUtils.isFalse(vo.getCheckCompanyId())) {
            sj.add("子公司不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckMaxReworkCount())) {
            sj.add("最大返修单不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckMaxReworkReminderCount())) {
            sj.add("最大返修单催单量不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckMaxHandCount())) {
            sj.add("最大手头单不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckMaxDayHandNumber())) {
            sj.add("最大当日手头单不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckDistributeNewCount())) {
            sj.add("每日新单派单量不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckMaxDeliveryAndWaitPartCount())) {
            sj.add("最大拉修待件数量不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckBindGridCount())) {
            sj.add("绑定副网格数量不满足");
        }
        if (BooleanUtils.isFalse(vo.getCheckStock())) {
            sj.add("动态库存不满足");
        }
        return reason + sj;
    }

    /**
     * 网格化查询派单工程师
     */
    @Override
    public void gridGetOrderDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        // 获取派单参数
        if (distributeConfigDRO == null) {
            distributeConfigDRO = this.getDistributeConfig(orderWork);
        }

        // 按以下顺序处理：新单/返修，CBF业务类型
        switch (orderWork.getType()) {

            // 新单
            case OrderConsts.ORDER_TYPE_NEW: {

                if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                    this.gridGetNewOrderDistributeMasterListTypeC(orderWork, orderDetail, distributeVO, distributeConfigDRO);
                } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                    this.gridGetNewOrderDistributeMasterListTypeF(orderWork, orderDetail, distributeVO, distributeConfigDRO);
                }

                break;
            }

            // 返修单
            case OrderConsts.ORDER_TYPE_REWORK: {
                if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
                    this.gridGetReworkOrderDistributeMasterListTypeC(orderWork, orderDetail, distributeVO, distributeConfigDRO);
                } else if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_F) {
                    this.gridGetReworkOrderDistributeMasterListTypeF(orderWork, orderDetail, distributeVO, distributeConfigDRO);
                }

                break;
            }

            default:
                break;
        }

        // 统一标记网格内或网格外

        // 网格内
        if (CollectionUtils.isNotEmpty(distributeVO.getMasterList())) {
            distributeVO.getMasterList().forEach((item) -> {
                item.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);
            });
        }

        // 网格外
        if (CollectionUtils.isNotEmpty(distributeVO.getNonGridDistributeMasterList())) {
            distributeVO.getNonGridDistributeMasterList().forEach((item) -> {
                item.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_OUT);
            });
        }

    }

    /**
     * 调用工程师dubbo获取网格化派单工程师列表
     *
     * @param distributeMasterQuery
     * @return
     */

    private List<ZsOrderDistributeVO> listGridDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());

        return this.listGridDistributeMasterByQuery(distributeMasterQuery, servSkillLists);
    }

    private List<ZsOrderDistributeVO> listGridDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery, List<List<DistributeOrderSkillQuery>> servSkillLists) {

        // 生成调用参数
        //PlatDirectlySendQuery platDirectlySendQuery = new PlatDirectlySendQuery();
        EngineerSimpleDistributeOrderQuery platDirectlySendQuery = new EngineerSimpleDistributeOrderQuery();

        platDirectlySendQuery.setSerialNumber(UUID.randomUUID().toString());

        platDirectlySendQuery.setPlat(distributeMasterQuery.getPlat());
        platDirectlySendQuery.setBizType(distributeMasterQuery.getBizType());
        platDirectlySendQuery.setChannelId(distributeMasterQuery.getChannelId());
        platDirectlySendQuery.setCityId(distributeMasterQuery.getCityId());
        platDirectlySendQuery.setOrderLat(distributeMasterQuery.getLatitude());
        platDirectlySendQuery.setOrderLng(distributeMasterQuery.getLongitude());
        platDirectlySendQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        platDirectlySendQuery.setServCategId(distributeMasterQuery.getServCategId());
        platDirectlySendQuery.setCategId(distributeMasterQuery.getShowCategId());
        platDirectlySendQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());
        platDirectlySendQuery.setMatchEngineerList(distributeMasterQuery.getMatchMasterIdList());
        platDirectlySendQuery.setExcludeEngineerList(distributeMasterQuery.getExcludeMasterIdList());

        // 后台技能
        platDirectlySendQuery.setServSkillList(servSkillLists);
        // 最大试用期
        platDirectlySendQuery.setMaxProbationCycle(7);

        // 调用查询派单工程师接口
        // todo fubiao
        logger.info("listGridDistributeMasterByQuery#listForSimpleDistributeOrder 入参：{}", JSON.toJSONString(platDirectlySendQuery));
        ResponseDTO<List<EngineerDistributeOrderDRO>> responseDTO = platDistributeOrderListRemoteService.listForSimpleDistributeOrder(platDirectlySendQuery);
        logger.info("listGridDistributeMasterByQuery#listForSimpleDistributeOrder 出参  [responseDTO]：{}", responseDTO);

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngineerDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();
        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }

    // 以下为网格化私有方法

    /**
     * 网格化查询新单派单工程师 Type C
     */
    private void gridGetNewOrderDistributeMasterListTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        logger.info("gridGetNewOrderDistributeMasterListTypeC");

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        /// 后门开关：默认打开
        boolean backdoorStatus = true;
        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        if (distributeArgsDRO != null) {
//            if (Objects.equals(distributeArgsDRO.getBackdoorStatus(), GlobalConsts.NO)) {
//                backdoorStatus = false;
//            }

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        if (backdoorStatus) {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
        } else {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.NO);
        }

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        // 查询网格外不可派单工程师列表
        this.gridGetNotInGridMasterList(orderWork, orderDetail, masterList, maxReworkCount, maxReworkReminderCount, distributeVO);

        /*
        // 处理网格外不可派单工程师列表数据
        if (CollectionUtils.isNotEmpty(distributeVO.getNonGridDistributeMasterList())) {
            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(distributeVO.getNonGridDistributeMasterList(), distributeMasterQuery);

            // 查询师傅统计信息并计算评分
            this.calcRecommendScore(distributeVO.getNonGridDistributeMasterList(), distributeMasterQuery, distributeArgsDRO);
        }
        */

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            logger.info("gridGetNewOrderDistributeMasterListTypeC:没有工程师");
            return;
        }

        // 初始化派单快照:不可派单列表
        distributeVO.setNonDistributeMasterList(Lists.newArrayListWithCapacity(masterList.size()));

        // 获取工程师列表网格信息
        this.getMasterListGridInfo(masterList, distributeMasterQuery);

        // 调用工程师服务查询app位置在线和服务范围状态
        this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 基础条件过滤，目前就是判断最大返修单量
        masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), distributeVO.getNonDistributeMasterList());

        // 基础条件过滤后没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            logger.info("gridGetNewOrderDistributeMasterListTypeC:基础条件过滤后没有工程师");
            return;
        }

        // 计算距离
        this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

        // 按主技能和手头单量排序
        this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

        // 只查询基础师傅列表，结束
        if (distributeVO.isOnlyBaseMasterList()) {

            // 保存简单派单师傅
            if (distributeVO.isSimpleStatus()) {
                distributeVO.setMasterList(masterList);
            }

            logger.info("gridGetNewOrderDistributeMasterListTypeC:只查询基础师傅列表");
            return;
        }

        /*
        // 非简单派单模式
        if (!distributeVO.isSimpleStatus()) {
            // 检查非直营工程师是否在线
            masterList = this.onlineStatusSnapshotFilter(masterList, distributeVO.getNonDistributeMasterList());

            // 过滤后没有工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info("gridGetNewOrderDistributeMasterListTypeC:非简单派单模式,检查非直营工程师是否在线");
                return;
            }
        }
        */

        // 查询师傅统计信息并计算评分
        this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);
        //logger.info("calcRecommendScore：" + masterList);

        List<ZsOrderDistributeVO> recommendMasterList = null;

        if (distributeVO.isRecommendStatus() || distributeVO.isFairStatus()) {

            if (CollectionUtils.isNotEmpty(masterList)) {

                if (distributeVO.isRecommendStatus()) {
                    // 推荐列表
                    recommendMasterList = this.getSortScoreMasterList(masterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                } else if (distributeVO.isFairStatus()) {
                    // 公平列表
                    recommendMasterList = this.getSortFairMasterList(masterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                }

                // 对推荐列表进行分组排序
                if (CollectionUtils.isNotEmpty(recommendMasterList)) {

                    // 获取工程师列表分组
                    List<List<ZsOrderDistributeVO>> roundMasterList = this.gridGroupMasterList(recommendMasterList, distributeMasterQuery);

                    // 将分组按顺序放入新列表
                    recommendMasterList = new ArrayList<>(recommendMasterList.size());

                    for (int i = 0; i < roundMasterList.size(); i++) {
                        recommendMasterList.addAll(roundMasterList.get(i));
                    }
                }
                else {
                    logger.info("gridGetNewOrderDistributeMasterListTypeC:推荐列表为空");
                }
            }
        }

        //logger.info("#recommendMasterList#:" + recommendMasterList);
        distributeVO.setRecommendMasterList(recommendMasterList);

        // 网格化暂时去掉：加载"非离职+技能+服务范围"的工程师（把上方满足条件的工程师排除在外）
        //List<ZsOrderDistributeVO> nonDistributeMasterList = this.listNonDistributeMaster(recommendMasterList, distributeMasterQuery);
        //distributeVO.setNonDistributeMasterList(nonDistributeMasterList);

        // 保存简单派单师傅
        if (distributeVO.isSimpleStatus()) {
            distributeVO.setMasterList(masterList);
        }

    }

    /**
     * 网格化查询新单派单工程师 Type F
     */
    private void gridGetNewOrderDistributeMasterListTypeF(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        logger.info("gridGetNewOrderDistributeMasterListTypeF");

        /// 后门开关：默认打开
        boolean backdoorStatus = true;

        // 构建查询
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        if (backdoorStatus) {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
        } else {
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.NO);
        }

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 按主技能和手头单量排序
        this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

        // 保存简单派单师傅
        if (distributeVO.isSimpleStatus()) {
            distributeVO.setMasterList(masterList);
        }

    }

    /**
     * 网格化查询返修单派单工程师 Type C
     */
    private void gridGetReworkOrderDistributeMasterListTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        logger.info("gridGetReworkOrderDistributeMasterListTypeC");

        // 返修原单工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        distributeVO.setReworkMasterId(reworkMasterId);

        // 最大手头返修单：默认0
        int maxReworkCount = 0;

        // 最大手头返修催单量：默认0
        int maxReworkReminderCount = 0;
        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        if (distributeArgsDRO != null) {
            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 查询原工程师
        ZsOrderDistributeVO reworkMaster = null;

        if (reworkMasterId != null && reworkMasterId > 0) {
            reworkMaster = this.findDistributeOrderByOriginalMaster(orderWork, distributeVO.getReworkMasterId(), true);
        }

        // 查询非原单工程师外的其他工程师
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 如果有返修原工程师，列表中排除原工程师
        if (reworkMasterId != null && reworkMasterId > 0) {
            List<Integer> excludeMasterIdList = new ArrayList<>(1);
            excludeMasterIdList.add(reworkMasterId);
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        // 查询其他工程师列表
        List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        // 处理返修工程师列表
        this.procReworkMasterList(distributeVO, reworkMaster, masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit());

        // 查询网格外不可派单工程师列表
        this.gridGetNotInGridMasterList(orderWork, orderDetail, distributeVO.getMasterList(), maxReworkCount, maxReworkReminderCount, distributeVO);
    }

    /**
     * 网格化查询返修单派单工程师 Type F
     */
    private void gridGetReworkOrderDistributeMasterListTypeF(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        logger.info("gridGetReworkOrderDistributeMasterListTypeF");

        // 返修原单工程师
        Integer reworkMasterId = orderWork.getReworkMasterId();
        distributeVO.setReworkMasterId(reworkMasterId);

        // 查询原工程师
        ZsOrderDistributeVO reworkMaster = null;

        if (reworkMasterId != null && reworkMasterId > 0) {
            reworkMaster = this.findDistributeOrderByOriginalMaster(orderWork, distributeVO.getReworkMasterId(), true);
        }

        // 查询非原单工程师外的其他工程师
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 如果有返修原工程师，列表中排除原工程师
        if (reworkMasterId != null && reworkMasterId > 0) {
            List<Integer> excludeMasterIdList = new ArrayList<>(1);
            excludeMasterIdList.add(reworkMasterId);
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        // 查询其他工程师列表
        List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        // 处理返修工程师列表
        this.procReworkMasterList(distributeVO, reworkMaster, masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, null);

        // 查询网格外不可派单工程师列表
        this.gridGetNotInGridMasterList(orderWork, orderDetail, distributeVO.getMasterList(), maxReworkCount, maxReworkReminderCount, distributeVO);
    }

    /**
     * 查询网格外不可派单工程师列表
     */
    private void gridGetNotInGridMasterList(OrderWork orderWork, OrderDetail orderDetail, List<ZsOrderDistributeVO> masterList, int maxReworkCount, int maxReworkReminderCount, DistributeVO distributeVO) {
        DistributeMasterQuery nonGridDistributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        if (CollectionUtils.isNotEmpty(masterList)) {
            // 排除可派的工程师
            List<Integer> excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
            nonGridDistributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        List<ZsOrderDistributeVO> nonGridDistributeMasterList = this.listMandatoryDistributeMasterByQuery(nonGridDistributeMasterQuery);

        if (CollectionUtils.isNotEmpty(nonGridDistributeMasterList)) {
            this.getMasterListWorkInfo(nonGridDistributeMasterList, nonGridDistributeMasterQuery);
            nonGridDistributeMasterList = this.baseDistributeFilter(nonGridDistributeMasterList, nonGridDistributeMasterQuery, maxReworkCount, maxReworkReminderCount, null);

            if (CollectionUtils.isNotEmpty(nonGridDistributeMasterList)) {
                this.getMasterOnlineStatusAndScopeStatus(nonGridDistributeMasterList, nonGridDistributeMasterQuery);
                this.calcMasterOrderDistance(nonGridDistributeMasterQuery.getLongitude(), nonGridDistributeMasterQuery.getLatitude(), nonGridDistributeMasterList);
                this.getEngineerAdjoinGrid(orderDetail, nonGridDistributeMasterList);
                distributeVO.setNonGridDistributeMasterList(nonGridDistributeMasterList);
            }
        }
    }

    /**
     * 网格化新单自动派单 Type C
     */
    private boolean gridNewOrderAutoDistributeTypeC(OrderWork orderWork, OrderDetail orderDetail, DistributeConfigDRO distributeConfigDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("gridNewOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + "-新单自动派单");

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        // 没有配置新单自动派单，结束
        if (distributeArgsDRO.getAutoStatusNew() == null
                || Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)
                || (!Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND) &&
                !Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR))) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            return false;
        }

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 获取自动派单工程师
        boolean ret = this.gridNewOrderAutoDistributeTypeCByQuery(distributeMasterQuery, distributeArgsDRO, distributeSnapshotVO, orderWork);
        if (!ret) {
            return false;
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = distributeSnapshotVO.getAutoDistributeMaster();
        if (distributeMaster == null) {
            return false;
        }

        // 保存新单自动派单
        logger.info("gridNewOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + "，新单自动派单成功：" + distributeMaster.getDistributeRuleText() + "，" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeMaster.getDistributeRuleText());
        distributeDTO.setDistributeRelateWorkText(distributeMaster.getDistributeRelateWorkText());
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(distributeMaster.getDistributeRule());
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        // 派单时间
        distributeDTO.setOperateTime(distributeSnapshotVO.getAutoDistributeTime());
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        // 派单网格
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        // 工程师中心点距离
        distributeDTO.setOrderCenterDistance(distributeMaster.getOrderCenterDistance());

        ret = this.saveAutoDistribute(distributeDTO);
        logger.info("gridNewOrderAutoDistributeTypeC:workId=" + orderWork.getWorkId() + "自动派单保存成功");

        return ret;
    }

    /**请假停单虚拟单量
     * 网格化新单自动派单 Type C By Query
     */
    private boolean gridNewOrderAutoDistributeTypeCByQuery(DistributeMasterQuery distributeMasterQuery, PlatDirectlyDistributeArgsDRO distributeArgsDRO, DistributeVO distributeSnapshotVO, OrderWork orderWork) {
        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + "-新单自动派单");

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        // 初始化派单快照:规则无
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_NONE);

        // 是否网格内派单
        boolean inGrid;

        do {

            // 最大手头返修单：默认0
            int maxReworkCount = 0;

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            // 最大返修催单量：默认0
            int maxReworkReminderCount = 0;
            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }

            // 初始化派单快照:不可派单列表
            distributeSnapshotVO.setNonDistributeMasterList(Lists.newArrayList());

            // 查询基础工程师列表
            List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

            // 网格内需要排除的工程师id
            List<Integer> excludeMasterIdList = null;

            // 网格内过滤
            if (CollectionUtils.isNotEmpty(masterList)) {

                // 网格内需要排除的工程师id
                excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
                // 获取工程师列表网格信息
                this.getMasterListGridInfo(masterList, distributeMasterQuery);

                // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
                this.getMasterListWorkInfo(masterList, distributeMasterQuery);

                // 基础条件过滤
                masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), distributeSnapshotVO.getNonDistributeMasterList());
            }

            // 过滤后没有网格内工程师
            if (CollectionUtils.isEmpty(masterList)) {
                inGrid = false;

                do {

                    // 突破组订单不走跨网格
                    if (Objects.equals(orderWork.getServProductGroupId(), 1028)) {
                        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + "," + inGrid + ",突破组订单不走跨网格");
                        break;
                    }

                    // 预约时间是否为今天
                    if (!DateUtil.isBetween(DateUtil.getDateStart(DateUtil.getNow()), DateUtil.getDateEnd(DateUtil.getNow()), orderWork.getDutyTime())) {
                        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + ",跨网格派单-预约时间非今日");
                        // 默认自动派单开始时间
                        String autoTimeStart = StringUtil.isNotBlank(distributeArgsDRO.getAutoTimeStart()) ? distributeArgsDRO.getAutoTimeStart() : "7:30";
                        boolean across = this.sendWaitDistribute(orderWork, null, autoTimeStart, 1, 0, 1, OrderDistributeConsts.DISTRIBUTE_RULE_REASON_DUTY_TIME_NOT_TODAY_ACROSS);
                        if (across) {
                            distributeSnapshotVO.setNonDistributeMasterList(null);
                            distributeSnapshotVO.setDistributeRule(null);
                        }
                        return false;
                    }

                    // 判断跨网格配置
                    if (!Objects.equals(distributeArgsDRO.getAcrossDistributeStatus(), com.zmn.consts.GlobalConsts.YES)) {
                        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + "," + inGrid + ",没有配置跨网格派单");
                        break;
                    }

                    if (distributeArgsDRO.getAcrossMaxTakeDistance() == null || distributeArgsDRO.getAcrossMaxTakeDistance() <= 0) {
                        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + "," + inGrid + ",跨网格派单工程师最大接单距离配置有误");
                        break;
                    }

                    if (NumberUtil.isNotNullOrZero(distributeArgsDRO.getAcrossDistributeWaitTime())) {
                        logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + ",跨网格派单等待时长" + distributeArgsDRO.getAcrossDistributeWaitTime() + "分钟");
                        boolean across = this.sendAcrossWaitDistribute(orderWork, distributeArgsDRO);
                        if (across) {
                            distributeSnapshotVO.setNonDistributeMasterList(null);
                            distributeSnapshotVO.setDistributeRule(null);
                            return false;
                        }
                    }

                    // 工程师最大接单距离
                    Integer acrossMaxTakeDistance = distributeArgsDRO.getAcrossMaxTakeDistance();

                    // 最大派单距离
                    Integer acrossMaxDistributeDistance = distributeArgsDRO.getAcrossMaxDistributeDistance();
                    if (acrossMaxDistributeDistance == null) {
                        acrossMaxDistributeDistance = 15;
                    }

                    // 辐射规则:每次递增5公里
                    int stepDistance = 5;

                    Integer minDistance = 0;
                    Integer maxDistance = stepDistance;

                    for ( ; maxDistance <= acrossMaxDistributeDistance; minDistance += stepDistance, maxDistance += stepDistance) {
                        logger.info(String.format("获取跨网格工程师:minDistance=%d,maxDistance=%d", minDistance, maxDistance));

                        // 获取跨网格工程师id列表
                        List<Integer> matchMasterIdList = this.getGridMasterIdList(distributeMasterQuery.getCityId(), distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), minDistance * 1000, maxDistance * 1000);

                        if (CollectionUtils.isEmpty(matchMasterIdList)) {
                            logger.info(String.format("获取跨网格工程师id为空:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                            continue;
                        }

                        // 排除网格内工程师id
                        distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
                        // 必须是上面获取到的跨网格工程师id
                        distributeMasterQuery.setMatchMasterIdList(matchMasterIdList);

                        //必须排除的工程师
                        if (NumberUtil.isNotNullOrZero(distributeMasterQuery.getExcludeMasterId())) {
                            if (CollectionUtil.isNullOrEmpty(excludeMasterIdList)) {
                                excludeMasterIdList = Lists.newArrayList();
                            }
                            excludeMasterIdList.add(distributeMasterQuery.getExcludeMasterId());
                            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
                        }

                        // 查询网格外工程师
                        masterList = this.listMandatoryDistributeMasterByQuery(distributeMasterQuery);
                        if (CollectionUtils.isEmpty(masterList)) {
                            logger.info(String.format("获取符合服务条件跨网格工程师为空:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                            continue;
                        }

                        // 本轮工程师id列表
                        List<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());

                        // 添加到需要排除的工程师id
                        if (excludeMasterIdList == null) {
                            excludeMasterIdList = masterIdList;
                        }
                        else {
                            excludeMasterIdList.addAll(masterIdList);
                        }

                        // 过滤家修匠工程师
                       /* masterList = this.jxjFilter(masterList);
                        if (CollectionUtils.isEmpty(masterList)) {
                            logger.info(String.format("只有家修匠工程师:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                            continue;
                        }*/

                        // 根据工程师手头单计算中心点
                        this.calcMasterListOrderCenter(masterList, distributeMasterQuery);

                        // 根据中心点距离过滤
                        masterList = this.orderCenterFilter(masterList, distributeMasterQuery, acrossMaxTakeDistance);
                        if (CollectionUtils.isEmpty(masterList)) {
                            logger.info(String.format("跨网格工程师距离不符合条件:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                            continue;
                        }

                        // 网格外过滤
                        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
                        this.getMasterListWorkInfo(masterList, distributeMasterQuery);
                        // 基础条件过滤

                        masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), distributeSnapshotVO.getNonDistributeMasterList());

                        if (CollectionUtils.isEmpty(masterList)) {
                            // 找到可服务的网格外工程师不符合基础过滤条件
                            logger.info(String.format("获取符合服务条件跨网格工程师不符合基础过滤条件:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                            continue;
                        }
                        else {
                            // 找到可服务的网格外工程师，结束处理
                            logger.info(String.format("获取符合服务条件跨网格工程师%d:minDistance=%d,maxDistance=%d", masterList.size(), minDistance, maxDistance));
                            break;
                        }

                    }

                    // 查询跨网格工程师后，将当前工单当日跨网格等待次数加1，今天再次跨网格派单时，不再等待时间
                    Date now = DateUtil.getNow();
                    Date dayEnd = DateUtil.getDateEnd(now);
                    int acrossCountOutTime = (int) (dayEnd.getTime() - now.getTime()) / 1000;
                    String acrossCountKey = String.format(RedisKeyConsts.ACROSS_DISTRIBUTE_WAIT_COUNT_ORDER, orderWork.getWorkId());
                    redisManager.setex(acrossCountKey, "1", acrossCountOutTime);

                } while (false);

            }
            else {
                inGrid = true;
            }

            // 基础条件过滤后，没有基础工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_FIND);
                break;
            }

            // 计算距离
            this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

            // 调用工程师服务查询app位置在线和服务范围状态
            this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

            // 相似订单优先判断
            distributeMaster = this.gridGetAutoDistributeSimilarMaster(masterList, distributeMasterQuery, distributeSnapshotVO);
            if (distributeMaster != null) {
                logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + ",相似订单");
                break;
            }

            // 数据准备工作，查询师傅统计信息并计算评分
            this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

            // 推荐条件过滤
            // masterList = this.recommendSnapshotFilter(masterList, distributeMasterQuery, distributeSnapshotVO.getNonDistributeMasterList());

            // 推荐条件标记
            this.recommendSnapshotMarker(masterList, distributeMasterQuery);

            distributeSnapshotVO.setMasterList(Lists.newArrayListWithCapacity(masterList.size()));

            // 派单轮次工程师列表分组，分组后取到一个能自动派的工程师为止，PS：网格内和网格外是不同分组

            List<List<ZsOrderDistributeVO>> roundMasterList = this.gridGroupMasterList(masterList, distributeMasterQuery);

            // 突破产品组特殊处理 走完相似 直接走家电突破公平规则
            if (!Objects.equals(orderWork.getServProductGroupId(), 1028)) {
                // 首轮派单最优师傅
                distributeMaster = this.gridGetAutoFirstOrderMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);

                if (distributeMaster == null) {

                    // 获取自动派单师傅
                    if (Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND)) {
                        // 多轮派单最优师傅
                        if (this.isManyProtection(distributeArgsDRO)) {
                            distributeMaster = this.gridGetAutoMastManyProtectionMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
                        }

                        // 试用工程师只走首轮和多轮 进入此处将试用工程师放入不可派单列表
                        List<ZsOrderDistributeVO> tryMasterList = masterList.stream().filter(vo -> Objects.equals(vo.getOaStatus(), EngineerOAStatusEnum.PROBATION.getCode())).collect(Collectors.toList());
                        distributeSnapshotVO.getNonDistributeMasterList().addAll(tryMasterList);
                        masterList.removeAll(tryMasterList);

                        // 分层分级 只有开启分级保护才进行处理
                        if (Objects.isNull(distributeMaster)
                                && Objects.equals(distributeArgsDRO.getEngineerLevelGroupStatus(), GlobalConsts.YES)) {
                            logger.info("临时日志 gridGradingGroupMasterList 执行");
                            this.gridGradingGroupMasterList(masterList, distributeMasterQuery, distributeArgsDRO);
                        }

                        // 推荐派 分级权重规则
                        if (Objects.isNull(distributeMaster) && Objects.equals(distributeMasterQuery.getGradingDistribute(), GlobalConsts.YES) && this.isHighQualityOrder(orderWork)) {
                            distributeMaster = this.gridGetAutoDistributeGradingScoreMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
                        }

                        // 推荐派
                        if (Objects.isNull(distributeMaster)) {
                            distributeMaster = this.gridGetAutoDistributeScoreMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
                        }
                    } else {
                        // 公平派
                        distributeMaster = this.gridGetAutoDistributeFairMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
                    }
                }
            }else {
                // 家电突破公平派单
                distributeMaster = this.gridGetAutoDistributeHomeAppliancesFairMaster(masterList, distributeMasterQuery, distributeSnapshotVO, distributeArgsDRO);
            }

            // 找到自动派单工程师，从列表删除
            if (Objects.nonNull(distributeMaster)) {
                distributeSnapshotVO.getMasterList().addAll(masterList);
                distributeSnapshotVO.getMasterList().remove(distributeMaster);
            }else {
                distributeSnapshotVO.getNonDistributeMasterList().addAll(masterList);
            }

        } while (false);

        if (distributeMaster == null) {
            logger.info("gridNewOrderAutoDistributeTypeCByQuery:workId=" + distributeMasterQuery.getWorkId() + ",新单自动派单：没有符合条件的工程师，结束");
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_FIND);
            return false;
        }

        // 记录派单网格
        Integer distributeGrid;

        if (inGrid) {
            // 网格内
            distributeGrid = OrderDistributeConsts.DISTRIBUTE_GRID_IN;
        }
        else {
            // 跨网格
            distributeGrid = OrderDistributeConsts.DISTRIBUTE_GRID_ACROSS;
        }

        distributeMaster.setDistributeGrid(distributeGrid);

        // 自动派单工程师保存到派单快照
        distributeSnapshotVO.setAutoDistributeMaster(distributeMaster);

        return true;
    }

    /**
     * 获取网格自动派单分级权重派单工程师
     * @param masterList
     * @param distributeMasterQuery
     * @param distributeSnapshotVO
     * @param distributeArgsDRO
     * @return
     */
    private ZsOrderDistributeVO gridGetAutoDistributeGradingScoreMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {
        // 没有师傅
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return null;
        }

        // 分级准入开关判断 未开启走原逻辑
        if (!Objects.equals(distributeArgsDRO.getEngineerLevelStatus(), GlobalConsts.YES)) {
            return null;
        }

        if (CollectionUtil.isNullOrEmpty(distributeArgsDRO.getEngineerLevelList())) {
            logger.info("分级准入开启，但无可入的级别！");
            return null;
        }
        // 1、过滤保留准入级别的工程师
        List<ZsOrderDistributeVO> accessMasterList = masterList.stream().filter(vo -> distributeArgsDRO.getEngineerLevelList().contains(vo.getHierarchyLevel())).collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(accessMasterList)) {
            logger.info("#gridGetAutoDistributeGradingScoreMaster#:没有准入级别的工程师");
            return null;
        }

        // 2、推荐权重分
        // 对剩下的待处理数据waitProcessList按分层分级推荐权重分降序排序
        this.sortMasterListByGradingRecommendScore(accessMasterList);
        ZsOrderDistributeVO vo = accessMasterList.get(0);
        vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND);
        vo.setDistributeRuleText(OrderDistributeConsts.getDistributeRuleName(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND));

        // 记录快照
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND);
        return vo;

/*
        // 1、过滤高等级工程师
        List<ZsOrderDistributeVO> highGradingMasterList = masterList.stream().filter(vo -> Objects.equals(vo.getHighGradeFlag(), GlobalConsts.YES)).collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(highGradingMasterList)) {
            logger.info("#gridGetAutoDistributeGradingScoreMaster#:没有高等级工程师");
            return null;
        }

        // 2、推荐权重分
        // 对剩下的待处理数据waitProcessList按推荐权重分降序排序
        this.sortMasterListByRecommendScore(highGradingMasterList);
        ZsOrderDistributeVO vo = highGradingMasterList.get(0);
        vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND);
        vo.setDistributeRuleText(OrderDistributeConsts.getDistributeRuleName(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND));

        // 记录快照
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_GRADING_RECOMMEND);
        return vo;*/
    }

    /**
     * 是否是优质订单
     * @param orderWork
     * @return
     */
    private boolean isHighQualityOrder(OrderWork orderWork) {
        Integer count = orderTagService.countOrderTagByOrderIdAndTagId(orderWork.getOrderId(), OrderTagConsts.TAG_ID_HIGH_QUALITY);
        return count > 0;
    }

    /**
     * 获取多轮自动派师傅-平台直派
     * @param masterList
     * @param distributeMasterQuery
     * @param distributeSnapshotVO
     * @param distributeArgsDRO
     * @return
     */
    private ZsOrderDistributeVO gridGetAutoMastManyProtectionMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {
        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        // 多伦保护只针对主网格 workspaceType 和 主技能
        List<ZsOrderDistributeVO> waitProcessList = this.gridProtectDistributeFilter(masterList, distributeMasterQuery);

        // 多轮保护
        List<ZsOrderDistributeVO> firstOrderMasterList = this.gridGetAutoManyProtectionMasterList(waitProcessList, distributeArgsDRO);

        // 如果有多轮保护的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
            ZsOrderDistributeVO vo = firstOrderMasterList.get(0);
            // 记录快照
            distributeSnapshotVO.setDistributeRule(vo.getDistributeRule());

            return vo;
        }
        return null;
    }

    /**
     * 获取首轮自动派师傅
     *   2022-06-13 平台直派（网格）首轮保护默认全部开启 多轮保护选开
     * @param masterList
     * @param distributeMasterQuery
     * @param distributeSnapshotVO
     * @param distributeArgsDRO
     * @return
     */
    private ZsOrderDistributeVO gridGetAutoFirstOrderMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {
        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        // 首轮师傅
        List<ZsOrderDistributeVO> firstOrderMasterList = this.gridGetAutoFirstOrderMasterList(masterList, distributeMasterQuery, distributeArgsDRO);

        // 如果有首轮优先的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
            ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
            return vo;
        }

        return null;
    }

    /**
     * 网格化返修自动派单
     */
    private boolean gridReworkOrderAutoDistribute(OrderWork orderWork, OrderDetail orderDetail, DistributeConfigDRO distributeConfigDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("gridReworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "-返修自动派单");

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        // 没有配置返修自动派单，结束
        if (!Objects.equals(distributeArgsDRO.getAutoStatusRework(), GlobalConsts.YES)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            return false;
        }

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 获取自动派单工程师
        boolean ret = this.gridReworkOrderAutoDistributeByQuery(distributeMasterQuery, distributeArgsDRO, distributeSnapshotVO);
        if (!ret) {
            return false;
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = distributeSnapshotVO.getAutoDistributeMaster();
        if (distributeMaster == null) {
            return false;
        }

        // 标记为网格内派单
        distributeMaster.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);

        // 保存返修自动派单
        logger.info("gridReworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "，返修自动派单成功：" + distributeMaster.getDistributeRuleText() + "，" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeMaster.getDistributeRuleText());
        distributeDTO.setDistributeRelateWorkText(distributeMaster.getDistributeRelateWorkText());
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(distributeMaster.getDistributeRule());
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        distributeDTO.setOperateTime(distributeSnapshotVO.getAutoDistributeTime());
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        ret = this.saveAutoDistribute(distributeDTO);
        logger.info("gridReworkOrderAutoDistribute:workId=" + orderWork.getWorkId() + "自动派单保存成功");

        return ret;
    }

    /**
     * 网格化返修自动派单 By Query
     */
    private boolean gridReworkOrderAutoDistributeByQuery(DistributeMasterQuery distributeMasterQuery, PlatDirectlyDistributeArgsDRO distributeArgsDRO, DistributeVO distributeSnapshotVO) {
        logger.info("gridReworkOrderAutoDistributeByQuery:workId=" + distributeMasterQuery.getWorkId() + "-返修自动派单");

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        // 初始化派单快照:规则无
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_NONE);

        do {

            // 最大手头返修单：默认0
            int maxReworkCount = 0;

            if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }

            // 最大返修催单量：默认0
            int maxReworkReminderCount = 0;
            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }

            // 初始化派单快照:不可派单列表
            distributeSnapshotVO.setNonDistributeMasterList(Lists.newArrayList());

            // 查询基础工程师列表
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
            List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

            // 基础条件过滤
            if (CollectionUtils.isNotEmpty(masterList)) {

                // 获取工程师列表网格信息
                this.getMasterListGridInfo(masterList, distributeMasterQuery);

                // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
                this.getMasterListWorkInfo(masterList, distributeMasterQuery);

                // 基础条件过滤
                masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), distributeSnapshotVO.getNonDistributeMasterList());
            }

            // 基础条件过滤后，没有基础工程师就不处理了
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info("gridReworkOrderAutoDistributeByQuery:workId=" + distributeMasterQuery.getWorkId()  + ",基础条件过滤后，没有工程师就不处理了");
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_FIND);
                break;
            }

            // 计算距离
            this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

            // 调用工程师服务查询app位置在线和服务范围状态
            this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

            // 数据准备工作，查询师傅统计信息并计算评分
            this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

            // 推荐条件标记
            this.recommendSnapshotMarker(masterList, distributeMasterQuery);

            // 返修公平只针对 主网格主技能的工程师师
            List<ZsOrderDistributeVO> roundMasterList = masterList.stream()
                    .filter(vo -> Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN))
                    .filter(vo -> Objects.equals(vo.getMainSkillId(), distributeMasterQuery.getMainSkillId()))
                    .collect(Collectors.toList());

            if (CollectionUtil.isNullOrEmpty(roundMasterList)) {
                logger.info("gridReworkOrderAutoDistributeByQuery:workId=" + distributeMasterQuery.getWorkId() + ",返修自动派单：没有主网格主技能的工程师，结束");
                return false;
            }

            // 获取自动派单师傅
            distributeMaster = this.gridGetAutoDistributeFairReworkMaster(roundMasterList, distributeMasterQuery, distributeSnapshotVO);

            if (distributeMaster != null) {
                // 找到自动派单工程师，从列表删除
                roundMasterList.remove(distributeMaster);
            }

            distributeSnapshotVO.setMasterList(roundMasterList);

            /*distributeSnapshotVO.setMasterList(Lists.newArrayListWithCapacity(masterList.size()));

            // 派单轮次工程师列表分组，分组后取到一个能自动派的工程师为止

            List<List<ZsOrderDistributeVO>> roundMasterList = this.gridGroupReworkMasterList(masterList, distributeMasterQuery);

            for (int i = 0; i < roundMasterList.size(); i++) {
                List<ZsOrderDistributeVO> tempMasterList = roundMasterList.get(i);

                if (CollectionUtils.isEmpty(tempMasterList)) {
                    continue;
                }

                if (distributeMaster == null) {

                    // 获取自动派单师傅
                    distributeMaster = this.gridGetAutoDistributeFairReworkMaster(tempMasterList, distributeMasterQuery, distributeSnapshotVO);

                    // 找到自动派单工程师，从列表删除
                    if (distributeMaster != null) {
                        for (int j = 0; j < tempMasterList.size(); j++) {
                            if (distributeMaster == tempMasterList.get(j)) {
                                tempMasterList.remove(j);
                                break;
                            }
                        }
                    }
                }

                // 将所有列表汇总到：派单快照-可派列表
                distributeSnapshotVO.getMasterList().addAll(tempMasterList);
            }*/

        } while (false);

        if (distributeMaster == null) {
            logger.info("gridReworkOrderAutoDistributeByQuery:workId=" + distributeMasterQuery.getWorkId() + ",返修自动派单：没有符合条件的工程师，结束");
            return false;
        }

        // 标记为网格内派单
        distributeMaster.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);

        // 自动派单工程师保存到派单快照
        distributeSnapshotVO.setAutoDistributeMaster(distributeMaster);

        return true;
    }

    /**
     * 网格内工程师列表分为八组
     */
    private List<List<ZsOrderDistributeVO>> gridGroupMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 分为12个组，优先级为：网格-->主技能-->库存
        List<List<ZsOrderDistributeVO>> groupMasterList = new ArrayList<>();

        // 组1：主网格-主技能-最佳库存
        List<ZsOrderDistributeVO> list1 = new ArrayList<>(masterList.size());
        groupMasterList.add(list1);

        // 组2：主网格-主技能-非最佳库存
        List<ZsOrderDistributeVO> list2 = new ArrayList<>(masterList.size());
        groupMasterList.add(list2);

        // 组3：主网格-非主技能-最佳库存
        List<ZsOrderDistributeVO> list3 = new ArrayList<>(masterList.size());
        groupMasterList.add(list3);

        // 组4：主网格-非主技能-非最佳库存
        List<ZsOrderDistributeVO> list4 = new ArrayList<>(masterList.size());
        groupMasterList.add(list4);

        // 组5：副网格-主技能-最佳库存
        List<ZsOrderDistributeVO> list5 = new ArrayList<>(masterList.size());
        groupMasterList.add(list5);

        // 组6：副网格-主技能-非最佳库存
        List<ZsOrderDistributeVO> list6 = new ArrayList<>(masterList.size());
        groupMasterList.add(list6);

        // 组7：副网格-非主技能-最佳库存
        List<ZsOrderDistributeVO> list7 = new ArrayList<>(masterList.size());
        groupMasterList.add(list7);

        // 组8：副网格-非主技能-非最佳库存
        List<ZsOrderDistributeVO> list8 = new ArrayList<>(masterList.size());
        groupMasterList.add(list8);

        // 组9：网格外-主技能-最佳库存
        List<ZsOrderDistributeVO> list9 = new ArrayList<>(masterList.size());
        groupMasterList.add(list9);

        // 组10：网格外-主技能-非最佳库存
        List<ZsOrderDistributeVO> list10 = new ArrayList<>(masterList.size());
        groupMasterList.add(list10);

        // 组11：网格外-非主技能-最佳库存
        List<ZsOrderDistributeVO> list11 = new ArrayList<>(masterList.size());
        groupMasterList.add(list11);

        // 组12：网格外-非主技能-非最佳库存
        List<ZsOrderDistributeVO> list12 = new ArrayList<>(masterList.size());
        groupMasterList.add(list12);

        for (ZsOrderDistributeVO vo : masterList) {

            if (Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN)) {
                if (Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组1：主网格-主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_ONE);
                        list1.add(vo);
                    }
                    else {
                        // 组2：主网格-主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_TWO);
                        list2.add(vo);
                    }
                }
                else {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组3：主网格-非主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_THREE);
                        list3.add(vo);
                    }
                    else {
                        // 组4：主网格-非主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_FOUR);
                        list4.add(vo);
                    }
                }
            }
            else if (Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_SLAVE)) {
                if (Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组5：副网格-主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_FIVE);
                        list5.add(vo);
                    }
                    else {
                        // 组6：副网格-主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_SIX);
                        list6.add(vo);
                    }
                }
                else {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组7：副网格-非主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_SEVEN);
                        list7.add(vo);
                    }
                    else {
                        // 组8：副网格-非主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_EIGHTH);
                        list8.add(vo);
                    }
                }
            }
            else {
                if (Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组9：网格外-主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_NINE);
                        list9.add(vo);
                    }
                    else {
                        // 组10：网格外-主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_TEN);
                        list10.add(vo);
                    }
                }
                else {
                    if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(vo.getStockType())) {
                        // 组11：网格外-非主技能-最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_ELEVEN);
                        list11.add(vo);
                    }
                    else {
                        // 组12：网格外-非主技能-非最佳库存
                        vo.setGroupId(OrderDistributeConsts.DISTRIBUTE_GROUP_NEW_TWELVE);
                        list12.add(vo);
                    }
                }
            }
        }

        return groupMasterList;
    }

    /**
     * 分层分级处理
     */
    private void gridGradingGroupMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, PlatDirectlyDistributeArgsDRO distributeArgsDRO) {
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return;
        }

        List<DistributeEngineerLevelGroupDRO> engineerLevelGroupList = distributeArgsDRO.getEngineerLevelGroupList();
        if (CollectionUtil.isNullOrEmpty(engineerLevelGroupList)) {
            return;
        }

        // 分级分层映射map
        Map<Integer, DistributeEngineerLevelGroupDRO> mappingMap = engineerLevelGroupList.stream()
                .flatMap(dro -> dro.getEngineerLevelList().stream().map(conf -> new AbstractMap.SimpleEntry<>(conf, dro)))
                .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));

        // 获取自然周及当日虚拟单量数据
        this.getMasterListNatureWeekInfo(masterList, distributeMasterQuery);

        int day = LocalDate.now().getDayOfWeek().getValue();

        // 层级参数赋值
        masterList.forEach(vo -> {
            DistributeEngineerLevelGroupDRO dro = mappingMap.get(vo.getHierarchyLevel());
            vo.setPriority(dro.getPriority());
            vo.setHierarchySortCount(0);
            Map<Integer, Integer> currentWeekProtectionCountMap = dro.getCurrentWeekProtectionCountMap();
            if (CollectionUtil.isNotNullOrEmpty(currentWeekProtectionCountMap)) {
                // 分层排序单量 = 当日新单量+自然周新单+当日请假停单虚拟单量+自然周请假停单虚拟单量-自然周开始到今日的总保护单量
                int hierarchySortCount = vo.getDistributeNewCount()
                        + Optional.ofNullable(vo.getNatureWeekDistributeNewCount()).orElse(0)
                        + Optional.ofNullable(vo.getTodaySleepVirtualCount()).orElse(0)
                        + Optional.ofNullable(vo.getSleepVirtualCount()).orElse(0)
                        - currentWeekProtectionCountMap.getOrDefault(day, 0);
                vo.setHierarchySortCount(hierarchySortCount);
            }
        });

    }

    /**
     *  返修工程师列表分为四组
     */
    private List<List<ZsOrderDistributeVO>> gridGroupReworkMasterList(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 分为4个组，优先级为：主副网格-->主技能
        List<List<ZsOrderDistributeVO>> groupMasterList = new ArrayList<>();

        // 组1：主网格-主技能
        List<ZsOrderDistributeVO> list1 = new ArrayList<>(masterList.size());
        groupMasterList.add(list1);

        // 组2：主网格-非主技能
        List<ZsOrderDistributeVO> list2 = new ArrayList<>(masterList.size());
        groupMasterList.add(list2);

        // 组3：副网格-主技能
        List<ZsOrderDistributeVO> list3 = new ArrayList<>(masterList.size());
        groupMasterList.add(list3);

        // 组4：副网格-非主技能
        List<ZsOrderDistributeVO> list4 = new ArrayList<>(masterList.size());
        groupMasterList.add(list4);

        for (ZsOrderDistributeVO vo : masterList) {

            if (Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN)) {
                if (Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
                    // 组1：主网格-主技能
                    list1.add(vo);
                }
                else {
                    // 组2：主网格-非主技能
                    list2.add(vo);
                }
            }
            else {
                if (Objects.equals(distributeMasterQuery.getMainSkillId(), vo.getMainSkillId())) {
                    // 组3：副网格-主技能
                    list3.add(vo);
                }
                else {
                    // 组4：副网格-非主技能
                    list4.add(vo);
                }
            }
        }

        return groupMasterList;
    }

    /**
     * 查强制派单工程师列表
     */
    @Override
    public List<ZsOrderDistributeVO> listMandatoryDistributeMaster(OrderWork orderWork, OrderDetail orderDetail) {
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        // 查询列表
        List<ZsOrderDistributeVO> masterList = this.listMandatoryDistributeMasterByQuery(distributeMasterQuery);

        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;

        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        if (distributeConfigDRO != null) {
            PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
            if (distributeArgsDRO != null && distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
                maxReworkCount = distributeArgsDRO.getReworkLimit();
            }
            if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
                maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
            }
        }

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 基础条件过滤
        masterList = this.baseDistributeFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount,null);

        if (CollectionUtils.isEmpty(masterList)) {
            return masterList;
        }

        // 计算距离
        this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

        return masterList;
    }

    /**
     * 保存派单快照
     * @param distributeSnapshot
     */
    @Override
    public void addDistributeSnapshot(DistributeSnapshot distributeSnapshot) {
        mongoTemplate.save(distributeSnapshot);
    }

    /**
     * 调用工程师dubbo获取强制派单工程师列表
     *
     * @param distributeMasterQuery
     * @return
     */

    private List<ZsOrderDistributeVO> listMandatoryDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery) {
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());

        return this.listMandatoryDistributeMasterByQuery(distributeMasterQuery, servSkillLists);
    }

    private List<ZsOrderDistributeVO> listMandatoryDistributeMasterByQuery(DistributeMasterQuery distributeMasterQuery, List<List<DistributeOrderSkillQuery >> servSkillLists) {

        // 生成调用参数
        EngineerEnforceDistributeOrderQuery platDirectlySendQuery = new EngineerEnforceDistributeOrderQuery();

        platDirectlySendQuery.setSerialNumber(UUID.randomUUID().toString());

        platDirectlySendQuery.setPlat(distributeMasterQuery.getPlat());
        platDirectlySendQuery.setBizType(distributeMasterQuery.getBizType());
        platDirectlySendQuery.setChannelId(distributeMasterQuery.getChannelId());
        platDirectlySendQuery.setCityId(distributeMasterQuery.getCityId());
        platDirectlySendQuery.setOrderLat(distributeMasterQuery.getLatitude());
        platDirectlySendQuery.setOrderLng(distributeMasterQuery.getLongitude());
        platDirectlySendQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        platDirectlySendQuery.setServCategId(distributeMasterQuery.getServCategId());
        platDirectlySendQuery.setCategId(distributeMasterQuery.getShowCategId());
        platDirectlySendQuery.setProductGroupId(distributeMasterQuery.getServProductGroupId());
        platDirectlySendQuery.setMatchEngineerList(distributeMasterQuery.getMatchMasterIdList());
        platDirectlySendQuery.setExcludeEngineerList(distributeMasterQuery.getExcludeMasterIdList());

        // 后台技能
        platDirectlySendQuery.setServSkillList(servSkillLists);

        platDirectlySendQuery.setMaxProbationCycle(7);

        // 调用查询派单工程师接口
        logger.info("listMandatoryDistributeMasterByQuery#listForEnforceDistributeOrder 入参：{}", JSON.toJSONString(platDirectlySendQuery));
        ResponseDTO<List<EngineerDistributeOrderDRO>> responseDTO = platDistributeOrderListRemoteService.listForEnforceDistributeOrder(platDirectlySendQuery);
        logger.info("listMandatoryDistributeMasterByQuery#listForEnforceDistributeOrder  出参 [responseDTO]：{}", JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<EngineerDistributeOrderDRO> distributeOrderDROList = responseDTO.getData();
        if (CollectionUtils.isEmpty(distributeOrderDROList)) {
            return Lists.newArrayListWithCapacity(0);
        }

        List<ZsOrderDistributeVO> distributeMasterList = Lists.newArrayListWithCapacity(distributeOrderDROList.size());
        distributeOrderDROList.forEach((item) -> {
            ZsOrderDistributeVO vo = this.transformDistributeObjectDRO2VO(item);
            distributeMasterList.add(vo);
        });

        return distributeMasterList;
    }

    /**
     * 调用GMS获取工程师列表网格信息
     *
     * @param masterList
     * @return
     */

    private void getMasterListGridInfo(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 工程师id集合
        List<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());

        // 生成调用参数
        EngineerInCoordGridTypeDIO engineerInCoordGridTypeDIO = new EngineerInCoordGridTypeDIO();
        engineerInCoordGridTypeDIO.setLat(distributeMasterQuery.getLatitude());
        engineerInCoordGridTypeDIO.setLng(distributeMasterQuery.getLongitude());
        engineerInCoordGridTypeDIO.setEngineerIdList(masterIdList);

        // 调用工程师网格信息接口
        logger.info("listEngineerGridTypeByLngAndLatAndEngineerIdList：{}", JSON.toJSONString(engineerInCoordGridTypeDIO));
        ResponseDTO<List<EngineerGridTypeDRO>> responseDTO = gridEngineerListRemoteService.listEngineerGridTypeByLngAndLatAndEngineerIdList(engineerInCoordGridTypeDIO);
        logger.info("listEngineerGridTypeByLngAndLatAndEngineerIdList[responseDTO]：{}", responseDTO);

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return;
        }

        // 保存结果到工程师列表
        Map<Integer, ZsOrderDistributeVO> masterMap = masterList.stream().collect(Collectors.toMap(ZsOrderDistributeVO::getMasterId, e -> e, (k1, k2) -> k1));
        List<EngineerGridTypeDRO> engineerGridTypeDROList = responseDTO.getData();
        ZsOrderDistributeVO vo;

        for (EngineerGridTypeDRO dro : engineerGridTypeDROList) {
            vo = masterMap.get(dro.getEngineerId());

            if (vo != null) {
                vo.setWorkspaceType(dro.getWorkspaceType());
                vo.setSlaveGridCount(dro.getSlaveGridCount());
            }
        }
    }

    /**
     * 调用GMS获取对应网格内工程师id列表
     *
     */
    private List<Integer> getGridMasterIdList(Integer cityId, Double lng, Double lat, Integer minDistance, Integer maxDistance) {

        // 生成调用参数
        DistanceGridEngInfoQuery distanceGridEngInfoQuery = new DistanceGridEngInfoQuery();
        distanceGridEngInfoQuery.setCityId(cityId);
        distanceGridEngInfoQuery.setLng(lng);
        distanceGridEngInfoQuery.setLat(lat);
        distanceGridEngInfoQuery.setMinDistance(minDistance);
        distanceGridEngInfoQuery.setMaxDistance(maxDistance);

        // 调用工程师网格信息接口
        logger.info("listGridEngineerByDistance：{}", JSON.toJSONString(distanceGridEngInfoQuery));
        ResponseDTO<List<Integer>> responseDTO = gridEngineerListRemoteService.listGridEngineerByDistance(distanceGridEngInfoQuery);
        logger.info("listGridEngineerByDistance[responseDTO]：{}", responseDTO);

        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return null;
        }

        return responseDTO.getData();
    }

    /**
     * 处理返修工程师列表
     */
    private void procReworkMasterList(DistributeVO distributeVO, ZsOrderDistributeVO reworkMaster, List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, int maxReworkCount, int maxReworkReminderCount, Integer supportGridCountLimit) {
        do {

            // 平台直派，获取源单工程师网格信息
            if (distributeMasterQuery.isGridDistribute() && reworkMaster != null) {
                List<ZsOrderDistributeVO> tempList = Lists.newArrayList(reworkMaster);
                this.getMasterListGridInfo(tempList, distributeMasterQuery);
            }

            // 没有其他工程师就不作后续处理了
            if (CollectionUtils.isEmpty(masterList)) {
                if (reworkMaster != null) {
                    // 有原单工程师，把原单工程师加到列表返回
                    distributeVO.setMasterList(Lists.newArrayList(reworkMaster));
                }

                break;
            }

            // 平台直派，获取其他工程师列表网格信息
            if (distributeMasterQuery.isGridDistribute()) {
                this.getMasterListGridInfo(masterList, distributeMasterQuery);
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            // 基础条件过滤，目前就是判断最大返修单量
            masterList = this.baseDistributeFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, supportGridCountLimit);

            // 基础条件过滤后没有工程师就不作后续处理了
            if (CollectionUtils.isEmpty(masterList)) {
                if (reworkMaster != null) {
                    // 有原单工程师，把原单工程师加到列表返回
                    distributeVO.setMasterList(Lists.newArrayList(reworkMaster));
                }

                break;
            }

            // 按主技能和手头单量排序
            this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

            // 如果没有返修原工程师，就返回查询列表
            if (reworkMaster == null) {
                distributeVO.setMasterList(masterList);
                break;
            }

            // 有返修原工程师，把原工程师放在查询列表最前面
            List<ZsOrderDistributeVO> allMasterList = Lists.newArrayListWithCapacity(masterList.size() + 1);
            allMasterList.add(reworkMaster);
            allMasterList.addAll(masterList);
            distributeVO.setMasterList(allMasterList);

        } while (false);

        // 调用工程师服务查询app位置在线和服务范围状态
        this.getMasterOnlineStatusAndScopeStatus(distributeVO.getMasterList(), distributeMasterQuery);

        // 计算距离
        this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), distributeVO.getMasterList());
    }

    /**
     * 网格获取自动相似派单师傅
     */
    private ZsOrderDistributeVO gridGetAutoDistributeSimilarMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 1.已派相似订单 ***/

        // 已派相似订单师傅列表
        List<ZsOrderDistributeVO> distributeSimilarOrderMasterList = this.getDistributeSimilarOrderMasterList(masterList, distributeMasterQuery, false);

        // 如果有相似已派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(distributeSimilarOrderMasterList)) {
            ZsOrderDistributeVO vo = distributeSimilarOrderMasterList.get(0);

            // 记录派单快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SIMILAR);
            distributeSimilarOrderMasterList.remove(0);
            distributeSnapshotVO.setMasterList(distributeSimilarOrderMasterList);

            // 已派相似关联工单文案
            String distributeRelateWorkText = this.getDistributedSimilarRelateWorkText(masterList, distributeMasterQuery, vo.getMasterId());
            vo.setDistributeRelateWorkText(distributeRelateWorkText);

            return vo;
        }

        /*** 2.未派相似订单 ***/

        List<EsOrderWork> esOrderWorks = this.getUnDistributeSimilarWorkList(distributeMasterQuery);

        // 未派相似订单师傅列表
        List<ZsOrderDistributeVO> unDistributeSimilarOrderMasterList = this.getUnDistributeSimilarOrderMasterList(esOrderWorks, masterList, distributeMasterQuery, false);

        // 如果有相似未派订单的师傅,满足推荐条件直接返回
        if (CollectionUtils.isNotEmpty(unDistributeSimilarOrderMasterList)) {
            ZsOrderDistributeVO vo = unDistributeSimilarOrderMasterList.get(0);

            // 记录派单快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_MULTI);
            unDistributeSimilarOrderMasterList.remove(0);
            distributeSnapshotVO.setMasterList(unDistributeSimilarOrderMasterList);

            // 未派相似关联工单文案
            String distributeRelateWorkText = this.getUnDistributeSimilarRelateWorkText(esOrderWorks);
            vo.setDistributeRelateWorkText(distributeRelateWorkText);

            return vo;
        }

        // 返回空
        logger.info("#gridGetAutoDistributeSimilarMaster#:" + distributeMasterQuery.getOrderId() + ",没找到可自动派单的师傅");
        return null;
    }

    /**
     * 网格获取自动推荐派单师傅
     */
    private ZsOrderDistributeVO gridGetAutoDistributeScoreMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, DistributeArgsDRO distributeArgsDRO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 1.保护优先 ***/

     /*   if (this.isManyProtection(distributeArgsDRO)) {

            // 多轮保护
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoManyProtectionMasterList(masterList, distributeArgsDRO);

            // 如果有多轮保护的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(vo.getDistributeRule());
                //firstOrderMasterList.remove(0);
                //distributeSnapshotVO.setMasterList(firstOrderMasterList);
                return vo;
            }
        }
        else {

            // 首轮师傅
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoFirstOrderMasterList(masterList, distributeMasterQuery);

            // 如果有首轮优先的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                //firstOrderMasterList.remove(0);
                //distributeSnapshotVO.setMasterList(firstOrderMasterList);

                return vo;
            }
        }
*/
        // 工程师分级分组保护开关判断 未开启走原逻辑
        if (Objects.equals(distributeArgsDRO.getEngineerLevelGroupStatus(), GlobalConsts.YES)) {
            this.sortMasterListByGradingRecommendScore(masterList);
            ZsOrderDistributeVO vo = masterList.get(0);
            vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_RECOMMEND);
            vo.setDistributeRuleText("推荐权重分最高");
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_RECOMMEND);
            return vo;
        }


        /*** 2.推荐权重分 ***/

        // 对剩下的待处理数据waitProcessList按推荐权重分降序排序
        List<ZsOrderDistributeVO> recommendScoreMasterList = this.getRecommendScoreList(masterList);

        if (CollectionUtils.isNotEmpty(recommendScoreMasterList)) {
            ZsOrderDistributeVO vo = recommendScoreMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_RECOMMEND);
            //recommendScoreMasterList.remove(0);
            //distributeSnapshotVO.setMasterList(recommendScoreMasterList);

            return vo;
        }

        // 返回空
        logger.info("#gridGetAutoDistributeScoreMaster#:" + distributeMasterQuery.getOrderId() + ",没找到可自动派单的师傅");
        return null;
    }

    /**
     * 网格获取自动公平派单师傅
     */
    private ZsOrderDistributeVO gridGetAutoDistributeFairMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, DistributeArgsDRO distributeArgsDRO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 1.保护优先 ***/

       /* if (this.isManyProtection(distributeArgsDRO)) {

            // 多轮保护
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoManyProtectionMasterList(masterList, distributeArgsDRO);

            // 如果有多轮保护的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(vo.getDistributeRule());
                //firstOrderMasterList.remove(0);
                //distributeSnapshotVO.setMasterList(firstOrderMasterList);

                return vo;
            }
        }
        else {

            // 首轮师傅
            List<ZsOrderDistributeVO> firstOrderMasterList = this.getAutoFirstOrderMasterList(masterList, distributeMasterQuery);

            // 如果有首轮优先的师傅,满足推荐条件直接返回
            if (CollectionUtils.isNotEmpty(firstOrderMasterList)) {
                ZsOrderDistributeVO vo = firstOrderMasterList.get(0);

                // 记录快照
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FIRST);
                //firstOrderMasterList.remove(0);
                //distributeSnapshotVO.setMasterList(firstOrderMasterList);

                return vo;
            }
        }*/

        /*** 2.公平原则 ***/

        // 对剩下的待处理数据waitProcessList按公平原则过滤和排序
//        List<ZsOrderDistributeVO> fairRuleMasterList = this.getFairRuleList(masterList);
        List<ZsOrderDistributeVO> fairRuleMasterList = this.gridGetFairRuleList(masterList);

        if (CollectionUtils.isNotEmpty(fairRuleMasterList)) {
            ZsOrderDistributeVO vo = fairRuleMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR);
            //fairRuleMasterList.remove(0);
            //distributeSnapshotVO.setMasterList(fairRuleMasterList);

            return vo;
        }

        // 2.公平原则-end

        // 返回空
        logger.info("#gridGetAutoDistributeFairMaster#:" + distributeMasterQuery.getOrderId() + ",没找到可自动派单的师傅");
        return null;
    }

    /**
     * 网格获取自动家电突破公平派单师傅
     */
    private ZsOrderDistributeVO gridGetAutoDistributeHomeAppliancesFairMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO, DistributeArgsDRO distributeArgsDRO) {
        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 家电突破——公平原则 ***/
        // 突破公平只针对主网格工程师
        List<ZsOrderDistributeVO> waitMasterList = masterList.stream()
                .filter(vo -> Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN)).collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(waitMasterList)) {
            return null;
        }
        // 家电突破-公平排序
        this.gridSortMasterListByHomeAppliancesFairRule(waitMasterList);
        ZsOrderDistributeVO vo = waitMasterList.get(0);
        vo.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_HOME_APPLIANCES_FAIR);
        vo.setDistributeRuleText(OrderDistributeConsts.getDistributeRuleName(OrderDistributeConsts.DISTRIBUTE_RULE_HOME_APPLIANCES_FAIR));
//        vo.setDistributeRelateWorkText(OrderDistributeConsts.getDistributeRuleName(OrderDistributeConsts.DISTRIBUTE_RULE_HOME_APPLIANCES_FAIR));
        // 记录快照
        distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_HOME_APPLIANCES_FAIR);
        return vo;
    }


    /**
     * 网格获取自动返修公平派单师傅
     */
    private ZsOrderDistributeVO gridGetAutoDistributeFairReworkMaster(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, DistributeVO distributeSnapshotVO) {

        // 没有师傅
        if (CollectionUtils.isEmpty(masterList)) {
            return null;
        }

        /*** 1.返修公平原则 ***/

        List<ZsOrderDistributeVO> fairRuleMasterList = this.getFairReworkRuleList(masterList);

        if (CollectionUtils.isNotEmpty(fairRuleMasterList)) {
            ZsOrderDistributeVO vo = fairRuleMasterList.get(0);

            // 记录快照
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_FAIR_REWORK);
            //fairRuleMasterList.remove(0);
            //distributeSnapshotVO.setMasterList(fairRuleMasterList);

            return vo;
        }

        // 1.返修公平原则-end

        // 返回空
        logger.info("#gridGetAutoDistributeFairReworkMaster#:" + distributeMasterQuery.getOrderId() + ",没找到可自动派单的师傅");
        return null;
    }

    /**
     * 校验工程师不能判断原因
     * @param orderWork
     * @param orderDetail
     * @param masterId
     * @return
     */
    private EngineerSupportDistributeOrderDRO checkNonDistributeReason(OrderWork orderWork, OrderDetail orderDetail, Integer masterId) {
        // 构建查询
        boolean isGridDistribute = Objects.equals(orderWork.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, isGridDistribute);
        distributeMasterQuery.setMasterId(masterId);
        // 返修原单工程师
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            distributeMasterQuery.setOriginalMasterId(masterId);
        }

        // 调用工程师服务检查基本条件
        EngineerSupportDistributeOrderQuery cannotDistributeOrderReasonQuery = new EngineerSupportDistributeOrderQuery();
        cannotDistributeOrderReasonQuery.setSerialNumber(UUID.randomUUID().toString());
        cannotDistributeOrderReasonQuery.setEngineerId(distributeMasterQuery.getMasterId());
        cannotDistributeOrderReasonQuery.setOriginalEngineerId(distributeMasterQuery.getOriginalMasterId());
        cannotDistributeOrderReasonQuery.setPlat(distributeMasterQuery.getPlat());
        cannotDistributeOrderReasonQuery.setBizType(distributeMasterQuery.getBizType());
        cannotDistributeOrderReasonQuery.setChannelId(distributeMasterQuery.getChannelId());
        cannotDistributeOrderReasonQuery.setSubCompanyId(distributeMasterQuery.getCompanyId());
        cannotDistributeOrderReasonQuery.setSpCompanyId(distributeMasterQuery.getManageCompanyId());
        cannotDistributeOrderReasonQuery.setCityId(distributeMasterQuery.getCityId());
        cannotDistributeOrderReasonQuery.setOrderLat(distributeMasterQuery.getLatitude());
        cannotDistributeOrderReasonQuery.setOrderLng(distributeMasterQuery.getLongitude());
        cannotDistributeOrderReasonQuery.setDutyTime(distributeMasterQuery.getDutyTime());
        // PS:网格化差异点
        cannotDistributeOrderReasonQuery.setGridScreen(isGridDistribute ? GlobalConsts.YES : GlobalConsts.NO);

        // 后台技能
        List<List<DistributeOrderSkillQuery>> servSkillLists = this.buildSkillQueryLists(distributeMasterQuery.getProductId(),
                distributeMasterQuery.getShowProductId(), distributeMasterQuery.getServCategId(), distributeMasterQuery.getCategId());
        cannotDistributeOrderReasonQuery.setServSkillList(servSkillLists);

        // 后门开关永远开
        Integer backDoorStatus = GlobalConsts.YES;
        cannotDistributeOrderReasonQuery.setSkipServAreaCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setSkipOnlineCheck(backDoorStatus);
        cannotDistributeOrderReasonQuery.setMaxProbationCycle(7);
        logger.info("检查师傅不能被派单原因入参:[{}]", JSON.toJSONString(cannotDistributeOrderReasonQuery));
        ResponseDTO<EngineerSupportDistributeOrderDRO> responseDTO = distributeOrderAssistListRemoteService.checkEngineerSupportDistributeOrder(cannotDistributeOrderReasonQuery);
        logger.info("检查师傅不能被派单原因出参:[{}]", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            return null;
        }
        return responseDTO.getData();
    }

    /**
     * 网格新单自动派单给指定工程师 Type C
     */
    private boolean gridNewOrderAutoDistribute2MasterTypeC(OrderWork orderWork, OrderDetail orderDetail, Integer masterId, DistributeConfigDRO distributeConfigDRO, Integer autoDistributeCount, DistributeVO distributeSnapshotVO) throws OmsBaseException {
        logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + "-新单自动派单给指定工程师:" + masterId);

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        // 最大手头返修单：默认0
        int maxReworkCount = 0;

        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        // 可自动派单的工程师
        ZsOrderDistributeVO distributeMaster = null;

        do {
            // 只查询指定工程师
            DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
            distributeMasterQuery.setMatchMasterIdList(Lists.newArrayList(masterId));
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

            // 查询推荐工程师列表
            // List<ZsOrderDistributeVO> recommendMasterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);
            List<ZsOrderDistributeVO> recommendMasterList = this.listMandatoryDistributeMasterByQuery(distributeMasterQuery);

            // 没有推荐工程师就不处理了
            if (CollectionUtils.isEmpty(recommendMasterList)) {
                logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，指定工程师不符合条件");

                EngineerSupportDistributeOrderDRO nonDistributeReason = this.checkNonDistributeReason(orderWork, orderDetail, masterId);
                if (Objects.isNull(nonDistributeReason)) {
                    logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，查询指定工程师不能服务原因失败");
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：查询加单工程师不能服务原因失败");
                    break;
                }
                if (Objects.equals(nonDistributeReason.getDistributeOrderStatus(), com.zmn.consts.GlobalConsts.NO)) {
                    logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                    distributeSnapshotVO.setDistributeFailReason("加单工程师不满足，原因：" + nonDistributeReason.getNotDistributeOrderEnum().getName());
                }
                break;
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(recommendMasterList, distributeMasterQuery);

            // 基础条件过滤，目前就是判断最大返修单量
            //recommendMasterList = this.baseDistributeFilter(recommendMasterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit());
            distributeSnapshotVO.setNonDistributeMasterList(Lists.newArrayListWithCapacity(recommendMasterList.size()));
            recommendMasterList = this.baseDistributeSnapshotFilter(recommendMasterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), distributeSnapshotVO.getNonDistributeMasterList());

            // 基础条件过滤后，没有推荐工程师就不处理了
            if (CollectionUtils.isEmpty(recommendMasterList)) {
                logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，基础条件过滤后，指定工程师不符合条件");
                distributeSnapshotVO.setDistributeFailReason("加单工程师不满足");
                break;
            }

            this.getMasterListGridInfo(recommendMasterList, distributeMasterQuery);

            distributeMaster = recommendMasterList.get(0);
        } while (false);

        if (distributeMaster == null) {
            return false;
        }

        // 保存新单自动派单
        logger.info("gridNewOrderAutoDistribute2MasterTypeC:workId=" + orderWork.getWorkId() + ",masterId=" + masterId + "，新单自动派单给指定工程师：" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(orderWork.getOrderId());
        distributeDTO.setWorkId(orderWork.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText("指定工程师自动派");
        distributeDTO.setDistributeRelateWorkText(null);
        distributeDTO.setAutoDistributeCount(autoDistributeCount);
        // 派单规则
        distributeDTO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_SPECIAL_ENADD);
        // 派单路径
        distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        distributeDTO.setOperateTime(null);
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(false);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        this.saveAutoDistribute(distributeDTO);

        // 工程师加单特殊处理，永远返回true
        return true;
    }

    /**
     * 把工程师列表拆分为普通和动态库存两个列表 Type C
     */
    private void splitStockMasterList(Integer cityId, List<ZsOrderDistributeVO> masterList, List<ZsOrderDistributeVO> masterNormalList, List<ZsOrderDistributeVO> masterStockList) {
        if (CollectionUtils.isEmpty(masterList)) {
            return;
        }

        // 判断是否城市开通动态库存
        boolean isWhiteCity = orderStockBService.isWhiteWorkCity(cityId);
        if (isWhiteCity) {
            for (ZsOrderDistributeVO vo : masterList) {
                vo.setUseStock(true);
            }

            masterStockList.addAll(masterList);
            return;
        }

        // 获取动态库存工程师ID列表
        Set<Integer> stockMasterIdSet = orderStockBService.getStockMasterIdList();
        if (CollectionUtils.isEmpty(stockMasterIdSet)) {
            for (ZsOrderDistributeVO vo : masterList) {
                vo.setUseStock(false);
            }

            masterNormalList.addAll(masterList);
            return;
        }

        for (ZsOrderDistributeVO vo : masterList) {
            if (stockMasterIdSet.contains(vo.getMasterId())) {
                vo.setUseStock(true);
                masterStockList.add(vo);
            }
            else {
                vo.setUseStock(false);
                masterNormalList.add(vo);
            }
        }

    }

    /**
     * 获取预派工程师
     * @param distributeMasterQuery
     */
    @Override
    public DistributeVO getPreDistributeMaster(DistributeMasterQuery distributeMasterQuery) {

        // 设置为录单预派
        distributeMasterQuery.setPreDistribute(true);

        // 自动派单时间
        Date date = DateUtil.getNow();

        // 派单快照
        DistributeVO distributeSnapshotVO = new DistributeVO();
        distributeSnapshotVO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        distributeSnapshotVO.setAutoDistributeTime(date);

        do {

            // 派单参数
            DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(distributeMasterQuery);
            if (distributeConfigDRO == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
                break;
            }

            PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
            if (distributeArgsDRO == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_CONFIG);
                break;
            }

            // 获取自动派单工程师

            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
            distributeMasterQuery.setGradingDistribute(GlobalConsts.NO);
            this.gridNewOrderAutoDistributeTypeCByQuery(distributeMasterQuery, distributeArgsDRO, distributeSnapshotVO, null);

        } while (false);

        return distributeSnapshotVO;
    }

    /**
     * 获取预约推荐工程师列表
     * @param distributeMasterQuery
     */
    @Override
    public DistributeVO listDutyRecommendMaster(DistributeMasterQuery distributeMasterQuery) {
        DistributeVO distributeVO = new DistributeVO();

        do {

            // 查询基础工程师列表
            distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
            List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);
            if (CollectionUtils.isEmpty(masterList)) {
                break;
            }

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            // 基础条件过滤
            masterList = this.baseDutyRecommendFilter(masterList, distributeMasterQuery);
            distributeVO.setMasterList(masterList);
        } while(false);

        return distributeVO;
    }

    @Override
    public void addPlaceAnOrderDistribute(PlaceAnOrderPreDistribute placeAnOrderPreDistribute) {
        mongoTemplate.save(placeAnOrderPreDistribute);
    }

    @Override
    public PlaceAnOrderPreDistribute getPlaceAnOrderDistribute(Long workId) {
        if (NumberUtil.isNullOrZero(workId)) {
            return null;
        }

        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and("workId").is(workId);
        query.addCriteria(criteria);

        return mongoTemplate.findOne(query, PlaceAnOrderPreDistribute.class, MongodbConsts.OMS_PLACE_AN_ORDER_PRE_DISTRIBUTE);
    }

    /**
     * 自动派单给预派工程师
     * @param placeAnOrderPreDistribute
     */
    private boolean autoPreDistribute(PlaceAnOrderPreDistribute placeAnOrderPreDistribute, OrderWork orderWork) throws OmsBaseException {

        // 派单快照
        DistributeVO distributeSnapshotVO = placeAnOrderPreDistribute.getDistributeVO();

        // 预派工程师
        ZsOrderDistributeVO distributeMaster = distributeSnapshotVO.getAutoDistributeMaster();

        // 自动派单时间
        Date date = DateUtil.getNow();
        distributeSnapshotVO.setAutoDistributeTime(date);

        // 保存派单
        logger.info("autoPreDistribute:workId=" + placeAnOrderPreDistribute.getWorkId() + "，预派工程师派单成功：" + distributeMaster.getDistributeRuleText() + "，" + distributeMaster.getMasterId());
        OrderDistributeDTO distributeDTO = new OrderDistributeDTO();
        distributeDTO.setOrderId(placeAnOrderPreDistribute.getOrderId());
        distributeDTO.setWorkId(placeAnOrderPreDistribute.getWorkId());
        distributeDTO.setMasterId(distributeMaster.getMasterId());
        distributeDTO.setMasterName(distributeMaster.getMasterName());
        distributeDTO.setMasterPhone(distributeMaster.getMasterPhone());
        distributeDTO.setDistributeTypeText(distributeMaster.getDistributeRuleText());
        distributeDTO.setDistributeRelateWorkText(distributeMaster.getDistributeRelateWorkText());
        distributeDTO.setAutoDistributeCount(0);
        // 派单规则
        distributeDTO.setDistributeRule(distributeMaster.getDistributeRule());
        // 派单路径
        distributeDTO.setDistributeWay(orderWork.getDistributeWay());
        distributeDTO.setOperateTime(distributeSnapshotVO.getAutoDistributeTime());
        // 工作网格类型
        distributeDTO.setWorkspaceType(distributeMaster.getWorkspaceType());
        // 库存类型
        distributeDTO.setStockType(distributeMaster.getStockType());
        // 是否录单预派
        distributeDTO.setPreDistribute(true);
        distributeDTO.setDistributeGrid(distributeMaster.getDistributeGrid());
        boolean ret = this.saveAutoDistribute(distributeDTO);
        logger.info("autoPreDistribute:workId=" + placeAnOrderPreDistribute.getWorkId() + "自动派单保存成功");

        // 保存派单快照
        if (distributeSnapshotVO.getDistributeRule() != null && distributeSnapshotVO.getDistributeRule() > 0) {
            if (OrderDistributeConsts.distributeSnapshotList.contains(distributeSnapshotVO.getDistributeRule())) {
                DistributeSnapshot distributeSnapshot = BeanMapper.map(distributeSnapshotVO, DistributeSnapshot.class);
                distributeSnapshot.setWorkId(placeAnOrderPreDistribute.getWorkId());
                distributeSnapshot.setSnapshotId(Long.valueOf(DateUtil.dateFormatToString(date, FORMAT_DATETIME4)));
                distributeSnapshot.setDistributeRuleName(OrderDistributeConsts.getDistributeRuleName(
                        distributeSnapshot.getDistributeRule()));
                distributeSnapshot.setDistributeWayName(OrderDistributeConsts.getDistributeWayName(
                        distributeSnapshot.getDistributeWay()));
                distributeSnapshot.setCreateTime(date);
                this.addDistributeSnapshot(distributeSnapshot);
            }
        }

        return ret;
    }

    /**
     * 获取工程师库存类型
     */
    private Map<Integer, Integer> getMasterListStockType(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {
        List<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());

        DistributeMasterStockBO distributeMasterStockBO = DistributeMasterStockBO.builder()
                .engineerIdList(masterIdList)
                .dutyTime(distributeMasterQuery.getDutyTime())
                .orderId(distributeMasterQuery.getOrderId())
                .workId(distributeMasterQuery.getWorkId())
                .build();

        if (NumberUtil.isNullOrZero(distributeMasterQuery.getOrderId()) || NumberUtil.isNullOrZero(distributeMasterQuery.getWorkId())) {
            distributeMasterStockBO.setServCategId(distributeMasterQuery.getServCategId());
            distributeMasterStockBO.setShowCategId(distributeMasterQuery.getShowCategId());
            distributeMasterStockBO.setBizType(distributeMasterQuery.getBizType());
            distributeMasterStockBO.setCityId(distributeMasterQuery.getCityId());
            distributeMasterStockBO.setProductNumber(distributeMasterQuery.getProductNumber());
        }

        Map<Integer, Integer> masterStockMap = orderStockBService.canDistributeMaster(distributeMasterStockBO);

        return masterStockMap;
    }

    /**
     * 是否需要检查绑定网格数量
     */
    private boolean needCheckGridBind(DistributeMasterQuery distributeMasterQuery) {
        boolean checkBindGrid = false;

        do {
            if (!distributeMasterQuery.isGridDistribute()) {
                break;
            }

            if (StringUtil.isBlank(gridBindCity)) {
                break;
            }

            List<String> strings = Arrays.asList(gridBindCity.split(","));
            if (!strings.contains(String.valueOf(distributeMasterQuery.getCityId()))) {
                break;
            }

            checkBindGrid = true;
        } while (false);

        return checkBindGrid;
    }

    private boolean masterNeedCheckGridBind(ZsOrderDistributeVO vo) {
        return !Objects.equals(vo.getCompanyId(), CompanyConsts.ZMN_JXJ_COMPANY_ID);
    }

    /**
     * 是否多轮保护
     */
    private boolean isManyProtection(DistributeArgsDRO distributeArgsDRO) {
        if (distributeArgsDRO == null) {
            return false;
        }

        if (!Objects.equals(distributeArgsDRO.getAutoRecommendProtectionType(), ConfDistributeConsts.PROTECTION_MANY_RULE)) {
            return false;
        }

        return true;
    }

    /**
     * 根据工程师手头单计算中心点
     *
     * @param masterList
     * @param distributeMasterQuery
     * @return
     */
    private void calcMasterListOrderCenter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {

        // 判断预约时间
        if (Objects.isNull(distributeMasterQuery.getDutyTime())) {
            logger.info("[{}]预约时间为空，不计算手头单中心点", distributeMasterQuery.getOrderId());
            return;
        }

        // 判断师傅列表
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            logger.info("[{}]工程师为空，不计算手头单中心点", distributeMasterQuery.getOrderId());
            return;
        }

        // 查询工程师手头单
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 状态结果：已派单-已领单-已上门 / 进行中
        boolQueryBuilder.must(QueryBuilders.termsQuery("status",
                Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT)));
        boolQueryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

        // 新单，返修单
        boolQueryBuilder.must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));

        // 排除测试单
        boolQueryBuilder.must(QueryBuilders.termQuery("isTest", false));
        // 排除重复单
        boolQueryBuilder.must(QueryBuilders.termQuery("isDuplicate", false));
        // 排除剔除工程师绩效的工单标签
        boolQueryBuilder.mustNot(QueryBuilders.termsQuery("orderTagList.categoryIdList", Lists.newArrayList(OrderTagConsts.TAG_CATEGORY_ID_EXCLUDE_PERFORMANCE)));
        // 1028 排除突破组订单
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("servProductGroupId", 1028));
        // 排除拉修
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("hasDelivery", true));
        // 排除待件
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("hasWaitPart", true));

        // 预约时间同一天
        String dutyStartTimeStr = DateUtil.toString(DateUtil.getDateStart(distributeMasterQuery.getDutyTime()));
        String dutyEndTimeStr = DateUtil.toString(DateUtil.getDateEnd(distributeMasterQuery.getDutyTime()));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("dutyTime").gte(dutyStartTimeStr).lte(dutyEndTimeStr));

        // 包含工程师条件
        Set<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toSet());
        boolQueryBuilder.must(QueryBuilders.termsQuery("masterId", masterIdList));
        logger.debug("[{}]中心点查询语句：【{}】-【{}】", distributeMasterQuery.getOrderId(), boolQueryBuilder.toString(), JSON.toJSONString(boolQueryBuilder));

        NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 500));
        String[] columns = {"id", "masterId","contact.location"};
        SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
        searchQuery.addSourceFilter(sourceFilter);

        List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(searchQuery);
        List<Long> resultList = esOrderWorks.stream().map(EsOrderWork::getId).collect(Collectors.toList());
        logger.debug("[{}]查询结果：【{}】", JSON.toJSONString(resultList));
        // 预约时间没有手头单返回
        if (CollectionUtil.isNullOrEmpty(esOrderWorks)) {
            logger.info("[{}]工程师手头单为空", distributeMasterQuery.getOrderId());
            return;
        }

        // 根据工程师手头单计算中心点，保存到VO订单中心位置
        Map<Integer, List<EsOrderWork>> masterMap = esOrderWorks.stream().collect(Collectors.groupingBy(EsOrderWork::getMasterId));
        masterList.forEach(vo -> {
            List<EsOrderWork> list = masterMap.get(vo.getMasterId());
            logger.debug("[{}]工程师id[{}],工单数据:[{}]", distributeMasterQuery.getOrderId(), vo.getMasterId(), JSON.toJSONString(list));
            // 没有手头单返回，中心点为空
            if (CollectionUtil.isNullOrEmpty(list)) {
                return;
            }

            // 当手头单为1单时，手头单位置就是中心点
            if (list.size() == 1) {
                String[] latLngArray = list.get(0).getContact().getLocation().split(",");
                vo.setOrderCenterLat(Double.valueOf(latLngArray[0]));
                vo.setOrderCenterLng(Double.valueOf(latLngArray[1]));
                return;
            }

            // 当手头单大于1单时，计算中心点
            BigDecimal lat = new BigDecimal(0);
            BigDecimal lng = new BigDecimal(0);
            for (EsOrderWork esOrderWork : list) {
                String[] latLngArray = esOrderWork.getContact().getLocation().split(",");
                lat = lat.add(new BigDecimal(latLngArray[0]));
                lng = lng.add(new BigDecimal(latLngArray[1]));
            }

            Double latitude = lat.divide(new BigDecimal(list.size()), 6 , RoundingMode.HALF_UP).doubleValue();
            Double longitude = lng.divide(new BigDecimal(list.size()), 6 , RoundingMode.HALF_UP).doubleValue();

            vo.setOrderCenterLat(latitude);
            vo.setOrderCenterLng(longitude);
        });
        logger.debug("[{}]工程师手头单中心点出参：【{}】", distributeMasterQuery.getOrderId(), JSON.toJSONString(masterList));
    }


    /**
     * 过滤家修匠工程师
     *
     */
    private List<ZsOrderDistributeVO> jxjFilter(List<ZsOrderDistributeVO> masterList) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        for (ZsOrderDistributeVO vo : masterList) {
            if (!Objects.equals(vo.getCompanyId(), CompanyConsts.ZMN_JXJ_COMPANY_ID)) {
                descMasterList.add(vo);
            }
        }

        return descMasterList;
    }

    /**
     * 根据工程师中心点到订单的距离过滤
     *
     */
    private List<ZsOrderDistributeVO> orderCenterFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery, Integer acrossMaxTakeDistance) {
        List<ZsOrderDistributeVO> descMasterList = Lists.newArrayListWithCapacity(masterList.size());

        // 转换为米
        double maxTakeDistance = (double)acrossMaxTakeDistance * 1000;
        double distance;

        for (ZsOrderDistributeVO vo : masterList) {

            if (vo.getOrderCenterLat() == null || vo.getOrderCenterLng() == null) {
                continue;
            }

            // 计算工程师中心点到订单的距离
            distance = MathUtil.GetDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), vo.getOrderCenterLng(), vo.getOrderCenterLat());
            if (distance <= maxTakeDistance) {
                vo.setOrderCenterDistance(distance);
                descMasterList.add(vo);
            }
        }

        return descMasterList;
    }

    @Override
    public ZsOrderDistributeVO getRedistributeMaster(OrderWork orderWork, Integer masterId) throws OmsBaseException {
        // 派单快照
        DistributeVO distributeSnapshotVO = new DistributeVO();
        distributeSnapshotVO.setAutoDistributeTime(DateUtil.getNow());

        // 渠道是否配置了自动派单
        ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
        if (confOrderChannelDRO != null && !Objects.equals(confOrderChannelDRO.getAutoDistributeOrder(), com.zmn.consts.GlobalConsts.YES)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SPECIAL_CHANNEL);
            throw new OmsBaseException("该渠道订单不自动派单");
        }

        //  待取消，不允许自动派单 （新版跟单）
        Integer waitCancelStatus = workTrackBService.getUserWaitCancelStatus(orderWork.getOrderId(), orderWork.getWorkId());
        if (Objects.equals(waitCancelStatus, GlobalConsts.YES)) {
            throw new OmsBaseException("待取消，不可派单");
        }

        TrackWorkQuery query = new TrackWorkQuery();
        query.setOrderId(orderWork.getOrderId());
        query.setWorkId(orderWork.getWorkId());
        query.setNotStatus(TrackConsts.TRACK_STATUS_FINISHED);
        query.setPromoterTypeList(Lists.newArrayList(GlobalConsts.OPERATE_USER_TYPE_USER, GlobalConsts.OPERATE_USER_TYPE_MASTER));
        query.setNotTrackContentId(TrackConsts.TRACK_CONTENT_ID_REMINDER);
        ResponseDTO<Integer> listResponseDTO = trackWorkListRemoteService.countTrackByQuery(query);
        if (listResponseDTO.isSuccess() && listResponseDTO.getData() > 0) {
            throw new OmsBaseException("有待处理跟单，不可派单");

        }

        // 不是进行中的单不处理
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_STATUS);
            throw new OmsBaseException("工单不在进行中");
        }


        // 挂起状态，不自动派单
        if (Objects.equals(orderWork.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_SUSPEND);
            throw new OmsBaseException("挂起状态，不自动派单");
        }

        // 工单设置为不自动派单
        if (Objects.equals(orderWork.getAutoDistribute(), GlobalConsts.NO)) {
            throw new OmsBaseException("工单设置为不自动派单");
        }

        // 获取派单配置
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        // 获取派单配置 失败
        if (Objects.isNull(distributeConfigDRO) || Objects.isNull(distributeArgsDRO)) {
            // 获取派单配置为空 结束
            throw new OmsBaseException("获取派单配置为空");
        }

        // 默认自动派单起止时间
        String autoTimeStart = "7:30";
        String autoTimeEnd = "21:30";

        if (StringUtils.isNotBlank(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeStart()) && StringUtils.isNotBlank(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeEnd())) {
            autoTimeStart = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeStart();
            autoTimeEnd = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO().getAutoTimeEnd();
        }

        Date curTime = DateUtil.getNow();
        int intCurTime = curTime.getHours() * 100 + curTime.getMinutes();

        String[] strStartTime = autoTimeStart.split(":");
        int intStartTime = Integer.valueOf(strStartTime[0]) * 100 + Integer.valueOf(strStartTime[1]);

        String[] strEndTime = autoTimeEnd.split(":");
        int intEndTime = Integer.valueOf(strEndTime[0]) * 100 + Integer.valueOf(strEndTime[1]);

        //logger.info("autoDistribute:intCurTime=" + intCurTime + ",intStartTime=" + intStartTime + "intEndTime=" + intEndTime);
        if (intCurTime < intStartTime || intCurTime > intEndTime) {
            throw new OmsBaseException("不在自动派单时间内");
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        // 设置需过滤的工程师
        distributeMasterQuery.setExcludeMasterId(masterId);
        distributeMasterQuery.setExcludeMasterIdList(Collections.singletonList(masterId));
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);
        // 设置不触发分层分级
        distributeMasterQuery.setGradingDistribute(GlobalConsts.NO);


        // C端订单没有预约时间，不自动派单
        if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            if (orderWork.getDutyTime() == null) {
                distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_DUTY_TIME);
                throw new OmsBaseException("C端订单没有预约时间,不自动派单");
            }
        }

        // 没有配置新单自动派单，结束
        if (distributeArgsDRO.getAutoStatusNew() == null
                || Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FORBIDDEN)
                || (!Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_RECOMMEND) &&
                !Objects.equals(distributeArgsDRO.getAutoStatusNew(), ConfDistributeConsts.AUTO_STATUS_FAIR))) {
            distributeSnapshotVO.setDistributeRule(OrderDistributeConsts.DISTRIBUTE_RULE_REASON_AUTO_CONFIG);
            throw new OmsBaseException("没有配置新单自动派单");
        }

        // 新单
        if (!Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            throw new OmsBaseException("非C端订单，不自动派单");
        }
        // 获取自动派单工程师
        boolean ret = this.gridNewOrderAutoDistributeTypeCByQuery(distributeMasterQuery, distributeArgsDRO, distributeSnapshotVO, orderWork);

        // 可自动派单的工程师
        return distributeSnapshotVO.getAutoDistributeMaster();
    }

    @Override
    public List<ZsOrderDistributeVO> getRedistributeMasterList(OrderWork orderWork, OrderDetail orderDetail) {
        return this.getRedistributeMasterList(null, orderWork, orderDetail);
    }

    @Override
    public List<ZsOrderDistributeVO> getRedistributeMasterList(DistributeMasterQuery distributeMasterQuery, OrderWork orderWork, OrderDetail orderDetail) {
        // 获取派单参数
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        if (logger.isDebugEnabled()) {
            logger.debug("distributeConfigDRO:{}", distributeConfigDRO);
        }

        if (Objects.isNull(distributeConfigDRO) || Objects.isNull(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO())) {
            // 获取派单参数配置为空 结束
            logger.info("工单【{}】获取派单参数配置为空--结束。", orderWork.getOrderId());
            return null;
        }

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
        // 派单视图对象
        DistributeVO distributeVO = this.buildDistributeVO(orderWork, orderDetail, distributeArgsDRO, true);

        if (Objects.isNull(distributeMasterQuery)) {
            distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        }
        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        // 后门开关：默认打开
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 必须排除原工程师
        distributeMasterQuery.setExcludeMasterId(orderWork.getMasterId());

        List<ZsOrderDistributeVO> masterList = Lists.newArrayList();
        List<ZsOrderDistributeVO> nonDistributeMasterList = Lists.newArrayList();
        List<Integer> excludeMasterIdList = Lists.newArrayList();

        if (distributeVO.getDistributeBizType() == OrderDistributeConsts.DISTRIBUTE_BIZ_TYPE_C) {
            masterList = this.getNewGridInMasterListTypeC(distributeMasterQuery, distributeArgsDRO, masterList, nonDistributeMasterList, distributeVO, maxReworkCount, maxReworkReminderCount);
            // 网格内没有 获取跨网格工程师
            if (CollectionUtil.isNullOrEmpty(masterList) && Objects.equals(orderWork.getType(),OrderConsts.ORDER_TYPE_NEW)){
                // 新单查询跨网格工程师列表 返修单不查询
                masterList = this.getNewGridOutMasterListTypeC(distributeMasterQuery, distributeArgsDRO, masterList, nonDistributeMasterList, excludeMasterIdList, maxReworkCount, maxReworkReminderCount);
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("查询出的派单列表：{}", masterList);
        }
        return masterList;
    }

    @Override
    public Integer countJXJAvailableMaster(OrderWork orderWork, OrderDetail orderDetail) {
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        if (Objects.isNull(distributeConfigDRO) || Objects.isNull(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO())) {
            logger.info("工单【{}】未查到派单配置--结束。", orderWork.getOrderId());
            return 0;
        }
        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
        // 最大手头返修单：默认0
        int maxReworkCount = 0;

        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        // 特殊处理设置行政子公司为家修匠
        distributeMasterQuery.setGridCompanyId(CompanyConsts.ZMN_JXJ_COMPANY_ID);

        // 后门开关：默认打开
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 查询工程师列表
        List<ZsOrderDistributeVO> masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        // 网格内需要排除的工程师id
        List<Integer> excludeMasterIdList = null;
        //
        List<ZsOrderDistributeVO> nonDistributeMasterList = Lists.newArrayList();

        // 网格内过滤
        if (CollectionUtils.isNotEmpty(masterList)) {

            // 网格内需要排除的工程师id
            excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
            // 获取工程师列表网格信息
            this.getMasterListGridInfo(masterList, distributeMasterQuery);

            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);

            // 基础条件过滤
            masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), nonDistributeMasterList);
        }

        // 网格内是否存在家修匠可服务工程师
        if (CollectionUtil.isNotNullOrEmpty(masterList)) {
            if (logger.isDebugEnabled()) {
                logger.debug("网格内存在家修匠可服务工程师:{}", masterList);
            }
            return masterList.size();
        }


        // 查询跨网格工程师列表
        List<ZsOrderDistributeVO> gridOutMasterList = this.getNewGridOutMasterListTypeC(distributeMasterQuery,
                distributeArgsDRO,
                masterList,
                nonDistributeMasterList,
                excludeMasterIdList,
                maxReworkCount,
                maxReworkReminderCount);
        // 网格内是否存在家修匠可服务工程师
        if (CollectionUtil.isNotNullOrEmpty(gridOutMasterList)) {
            if (logger.isDebugEnabled()) {
                logger.debug("网格外存在家修匠可服务工程师：{}", gridOutMasterList);
            }
            return masterList.size();
        }
        return 0;
    }

    @Override
    public List<ZsOrderDistributeVO> getGridDistributeMasterList(OrderWork orderWork, OrderDetail orderDetail, EngineerRedistributeQuery engineerRedistributeQuery) {
        // 默认查找网格内的工程师
        if (NumberUtil.isNullOrZero(engineerRedistributeQuery.getDistributeGrid())) {
            engineerRedistributeQuery.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);
        }

        // 获取派单参数
        DistributeConfigDRO distributeConfigDRO = this.getDistributeConfig(orderWork);
        if (logger.isDebugEnabled()) {
            logger.debug("distributeConfigDRO:{}", distributeConfigDRO);
        }

        if (Objects.isNull(distributeConfigDRO) || Objects.isNull(distributeConfigDRO.getPlatDirectlyDistributeArgsDRO())) {
            // 获取派单参数配置为空 结束
            logger.info("工单【{}】获取派单参数配置为空--结束。", orderWork.getOrderId());
            return null;
        }

        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
        // 派单视图对象
        DistributeVO distributeVO = this.buildDistributeVO(orderWork, orderDetail, distributeArgsDRO, true);

        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);

        if (NumberUtil.isNotNullOrZero(engineerRedistributeQuery.getProductId())
                && !Objects.equals(engineerRedistributeQuery.getProductId(), orderWork.getProductId())) {
            distributeMasterQuery.setProductId(engineerRedistributeQuery.getProductId());
            distributeMasterQuery.setServCategId(engineerRedistributeQuery.getServCategId());
            distributeMasterQuery.setCategId(engineerRedistributeQuery.getCategId());
        }


        if ((Objects.nonNull(engineerRedistributeQuery.getLatitude()) && Objects.nonNull(engineerRedistributeQuery.getLongitude()))
                && (!Objects.equals(engineerRedistributeQuery.getLatitude(), orderDetail.getLatitude()) || !Objects.equals(engineerRedistributeQuery.getLongitude(), orderDetail.getLongitude()))) {
            distributeMasterQuery.setLatitude(engineerRedistributeQuery.getLatitude());
            distributeMasterQuery.setLongitude(engineerRedistributeQuery.getLongitude());
            distributeMasterQuery.setCountyId(engineerRedistributeQuery.getCountyId());
            distributeMasterQuery.setStreetId(engineerRedistributeQuery.getStreetId());
        }

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        // 后门开关：默认打开
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        // 必须排除原工程师
        distributeMasterQuery.setExcludeMasterId(orderWork.getMasterId());

        List<ZsOrderDistributeVO> masterList = Lists.newArrayList();
        List<ZsOrderDistributeVO> nonDistributeMasterList = Lists.newArrayList();
        List<Integer> excludeMasterIdList = Lists.newArrayList();
        //查询网格内可服务工程师
        masterList =  this.getNewGridInMasterListTypeC(distributeMasterQuery, distributeArgsDRO, masterList, nonDistributeMasterList, distributeVO, maxReworkCount, maxReworkReminderCount);
        if (Objects.equals(engineerRedistributeQuery.getDistributeGrid(), OrderDistributeConsts.DISTRIBUTE_GRID_IN)) {
            // 如果查询网格内直接返回
            return masterList;
        }else{
            // 因为网格外的需要排除网格内的工程师 所有需要先查网格内的工程师进行排除（工程师接口无满足接口）
            if (CollectionUtil.isNotNullOrEmpty(masterList)) {
                excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
            }
            excludeMasterIdList.add(orderWork.getMasterId());
            return this.getNewGridOutMasterListTypeC(distributeMasterQuery, excludeMasterIdList, maxReworkCount, maxReworkReminderCount);
        }
    }

    @Override
    public void gridGetOrderRedistributeVO(OrderWork orderWork, OrderDetail orderDetail, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        DistributeMasterQuery distributeMasterQuery = this.buildDistributeMasterQuery(orderWork, orderDetail, true);
        this.gridGetOrderRedistributeVO(distributeMasterQuery, distributeVO, distributeConfigDRO);
    }

    @Override
    public void gridGetOrderRedistributeVO(DistributeMasterQuery distributeMasterQuery, DistributeVO distributeVO, DistributeConfigDRO distributeConfigDRO) {
        PlatDirectlyDistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();

        if (Objects.isNull(distributeArgsDRO)) {
            logger.warn("平台直派派单配置未空");
            return;
        }

        // 最大手头返修单：默认0
        int maxReworkCount = 0;
        if (distributeArgsDRO.getReworkLimit() != null && distributeArgsDRO.getReworkLimit() > 0) {
            maxReworkCount = distributeArgsDRO.getReworkLimit();
        }

        // 最大返修催单量：默认0
        int maxReworkReminderCount = 0;
        if (distributeArgsDRO.getReworkReminderLimit() != null && distributeArgsDRO.getReworkReminderLimit() > 0) {
            maxReworkReminderCount = distributeArgsDRO.getReworkReminderLimit();
        }

        // 后门开关：默认打开
        distributeMasterQuery.setBackdoorStatus(GlobalConsts.YES);

        List<ZsOrderDistributeVO> masterList = Lists.newArrayList();
        List<ZsOrderDistributeVO> nonDistributeMasterList = Lists.newArrayList();
        List<Integer> excludeMasterIdList = Lists.newArrayList();
        //查询网格内可服务工程师
        masterList =  this.getNewGridInMasterListTypeC(distributeMasterQuery, distributeArgsDRO, masterList, nonDistributeMasterList, distributeVO, maxReworkCount, maxReworkReminderCount);


        if (CollectionUtil.isNotNullOrEmpty(masterList)) {
            excludeMasterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());
        }
        excludeMasterIdList.add(distributeMasterQuery.getExcludeMasterId());
        List<ZsOrderDistributeVO> noGridMasterList = this.getNewGridOutMasterListTypeC(distributeMasterQuery, excludeMasterIdList, maxReworkCount, maxReworkReminderCount);

        distributeVO.setRecommendMasterList(masterList);
        distributeVO.setNonGridDistributeMasterList(noGridMasterList);
    }

    /**
     * 获取网格内工程师列表-新单-type C
     * @param distributeMasterQuery 派单查询对象
     * @param distributeArgsDRO 派单配置
     * @param masterList 工程师列表
     * @param nonDistributeMasterList 不可派单工程师列表
     * @param distributeVO 派单视图对象
     * @param maxReworkCount 最大返修数量
     * @param maxReworkReminderCount 最大返修催单数量
     * @return
     */
    private List<ZsOrderDistributeVO> getNewGridInMasterListTypeC(DistributeMasterQuery distributeMasterQuery,
                                                               PlatDirectlyDistributeArgsDRO distributeArgsDRO,
                                                               List<ZsOrderDistributeVO> masterList,
                                                               List<ZsOrderDistributeVO> nonDistributeMasterList,
                                                               DistributeVO distributeVO,
                                                               int maxReworkCount,
                                                               int maxReworkReminderCount){
        //必须排除的工程师
        List<Integer> excludeMasterIdList = distributeMasterQuery.getExcludeMasterIdList();
        if (NumberUtil.isNotNullOrZero(distributeMasterQuery.getExcludeMasterId())) {
            if (CollectionUtil.isNullOrEmpty(excludeMasterIdList)) {
                excludeMasterIdList = Lists.newArrayList();
            }
            excludeMasterIdList.add(distributeMasterQuery.getExcludeMasterId());
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }
        logger.info("getNewGridInMasterListTypeC-workId:{}", distributeMasterQuery.getWorkId());
        // 查询工程师列表
        masterList = this.listGridDistributeMasterByQuery(distributeMasterQuery);

        // 没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            logger.info("getNewGridInMasterListTypeC-workId:{}:没有工程师", distributeMasterQuery.getWorkId());
            return masterList;
        }

        // 获取工程师列表网格信息
        this.getMasterListGridInfo(masterList, distributeMasterQuery);

        // 调用工程师服务查询app位置在线和服务范围状态
        this.getMasterOnlineStatusAndScopeStatus(masterList, distributeMasterQuery);

        // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
        this.getMasterListWorkInfo(masterList, distributeMasterQuery);

        // 基础条件过滤，目前就是判断最大返修单量
        masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), nonDistributeMasterList);

        // 基础条件过滤后没有工程师就不作后续处理了
        if (CollectionUtils.isEmpty(masterList)) {
            logger.info("getNewGridInMasterListTypeC-workId:{}:基础条件过滤后没有工程师", distributeMasterQuery.getWorkId());
            return masterList;
        }

        // 计算距离
        this.calcMasterOrderDistance(distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), masterList);

        // 按主技能和手头单量排序
        this.sortByMainSkillId(masterList, distributeVO.getMainSkillId());

        // 只查询基础师傅列表，结束
        if (distributeVO.isOnlyBaseMasterList()) {

            // 保存简单派单师傅
            if (distributeVO.isSimpleStatus()) {
                distributeVO.setMasterList(masterList);
            }
            // 统一标记网格内
            // 网格内
            masterList.forEach((item) -> {
                item.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);
            });
            logger.info("getNewGridInMasterListTypeC-workId:{}:只查询基础师傅列表", distributeMasterQuery.getWorkId());
            return masterList;
        }

        // 查询师傅统计信息并计算评分
        this.calcRecommendScore(masterList, distributeMasterQuery, distributeArgsDRO);

        List<ZsOrderDistributeVO> recommendMasterList = null;

        if (distributeVO.isRecommendStatus() || distributeVO.isFairStatus()) {

            if (CollectionUtils.isNotEmpty(masterList)) {

                if (distributeVO.isRecommendStatus()) {
                    // 推荐列表
                    recommendMasterList = this.getSortScoreMasterList(masterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                } else if (distributeVO.isFairStatus()) {
                    // 公平列表
                    recommendMasterList = this.getSortFairMasterList(masterList, distributeMasterQuery, distributeVO.getNonDistributeMasterList());
                }

                // 对推荐列表进行分组排序
                if (CollectionUtils.isNotEmpty(recommendMasterList)) {

                    // 获取工程师列表分组
                    List<List<ZsOrderDistributeVO>> roundMasterList = this.gridGroupMasterList(recommendMasterList, distributeMasterQuery);

                    // 将分组按顺序放入新列表
                    recommendMasterList = new ArrayList<>(recommendMasterList.size());

                    for (int i = 0; i < roundMasterList.size(); i++) {
                        recommendMasterList.addAll(roundMasterList.get(i));
                    }

                    // 统一标记网格内
                    // 网格内
                    recommendMasterList.forEach((item) -> {
                        item.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_IN);
                    });
                }
                else {
                    logger.info("getNewGridInMasterListTypeC-workId:{}:推荐列表为空", distributeMasterQuery.getWorkId());
                }
            }
        }
        logger.debug("getNewGridInMasterListTypeC-workId:{}:返回推荐列表:{}", distributeMasterQuery.getWorkId(), JSON.toJSONString(masterList));
        return recommendMasterList;
    }

    /**
     * 获取跨网格工程师列表-新单-C-自动派单-未排序
     * @param distributeMasterQuery 派单查询对象
     * @param distributeArgsDRO 派单配置
     * @param masterList 工程师列表
     * @param nonDistributeMasterList 不可派单工程师列表
     * @param excludeMasterIdList 排除的工程师Id列表
     * @param maxReworkCount 最大返修数量
     * @param maxReworkReminderCount 最大返修催单数量
     * @return
     */
    private List<ZsOrderDistributeVO> getNewGridOutMasterListTypeC(DistributeMasterQuery distributeMasterQuery,
                                                           PlatDirectlyDistributeArgsDRO distributeArgsDRO,
                                                           List<ZsOrderDistributeVO> masterList,
                                                           List<ZsOrderDistributeVO> nonDistributeMasterList,
                                                           List<Integer> excludeMasterIdList,
                                                           int maxReworkCount,
                                                           int maxReworkReminderCount) {
        // 判断跨网格配置
        if (!Objects.equals(distributeArgsDRO.getAcrossDistributeStatus(), com.zmn.consts.GlobalConsts.YES)) {
            logger.info("getAutoNewGridOutMasterListTypeC:workId=" + distributeMasterQuery.getWorkId() + ",没有配置跨网格派单");
            return null;
        }

        if (distributeArgsDRO.getAcrossMaxTakeDistance() == null || distributeArgsDRO.getAcrossMaxTakeDistance() <= 0) {
            logger.info("getAutoNewGridOutMasterListTypeC:workId=" + distributeMasterQuery.getWorkId() + ",跨网格派单工程师最大接单距离配置有误");
            return null;
        }

        // 工程师最大接单距离
        Integer acrossMaxTakeDistance = distributeArgsDRO.getAcrossMaxTakeDistance();

        // 最大派单距离
        Integer acrossMaxDistributeDistance = distributeArgsDRO.getAcrossMaxDistributeDistance();
        if (acrossMaxDistributeDistance == null) {
            acrossMaxDistributeDistance = 15;
        }

        // 辐射规则:每次递增5公里
        int stepDistance = 5;

        Integer minDistance = 0;
        Integer maxDistance = stepDistance;

        for (; maxDistance <= acrossMaxDistributeDistance; minDistance += stepDistance, maxDistance += stepDistance) {
            logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-获取跨网格工程师:minDistance=%d,maxDistance=%d", distributeMasterQuery.getWorkId(), minDistance, maxDistance));

            // 获取跨网格工程师id列表
            List<Integer> matchMasterIdList = this.getGridMasterIdList(distributeMasterQuery.getCityId(), distributeMasterQuery.getLongitude(), distributeMasterQuery.getLatitude(), minDistance * 1000, maxDistance * 1000);

            if (CollectionUtils.isEmpty(matchMasterIdList)) {
                logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-获取跨网格工程师id为空:minDistance=%d,maxDistance=%d", distributeMasterQuery.getWorkId(), minDistance, maxDistance));
                continue;
            }

            // 排除网格内工程师id
            distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
            // 必须是上面获取到的跨网格工程师id
            distributeMasterQuery.setMatchMasterIdList(matchMasterIdList);

            //必须排除的工程师
            if (NumberUtil.isNotNullOrZero(distributeMasterQuery.getExcludeMasterId())) {
                if (CollectionUtil.isNullOrEmpty(excludeMasterIdList)) {
                    excludeMasterIdList = Lists.newArrayList();
                }
                excludeMasterIdList.add(distributeMasterQuery.getExcludeMasterId());
                distributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
            }

            // 查询网格外工程师
            masterList = this.listMandatoryDistributeMasterByQuery(distributeMasterQuery);
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-获取符合服务条件跨网格工程师为空:minDistance=%d,maxDistance=%d", distributeMasterQuery.getWorkId(), minDistance, maxDistance));
                continue;
            }

            // 本轮工程师id列表
            List<Integer> masterIdList = masterList.stream().map(ZsOrderDistributeVO::getMasterId).collect(Collectors.toList());

            // 添加到需要排除的工程师id
            if (excludeMasterIdList == null) {
                excludeMasterIdList = masterIdList;
            } else {
                excludeMasterIdList.addAll(masterIdList);
            }

            // 根据工程师手头单计算中心点
            this.calcMasterListOrderCenter(masterList, distributeMasterQuery);

            // 根据中心点距离过滤
            masterList = this.orderCenterFilter(masterList, distributeMasterQuery, acrossMaxTakeDistance);
            if (CollectionUtils.isEmpty(masterList)) {
                logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-跨网格工程师距离不符合条件:minDistance=%d,maxDistance=%d", distributeMasterQuery.getWorkId(), minDistance, maxDistance));
                continue;
            }

            // 网格外过滤
            // 查询工单信息（手头单（不含待件&拉修），手头返修单（不含待件&拉修），当月已派他人返修单）
            this.getMasterListWorkInfo(masterList, distributeMasterQuery);
            // 基础条件过滤
            masterList = this.baseDistributeSnapshotFilter(masterList, distributeMasterQuery, maxReworkCount, maxReworkReminderCount, distributeArgsDRO.getSupportGridCountLimit(), nonDistributeMasterList);

            if (CollectionUtils.isEmpty(masterList)) {
                // 找到可服务的网格外工程师不符合基础过滤条件
                logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-获取符合服务条件跨网格工程师不符合基础过滤条件:minDistance=%d,maxDistance=%d", minDistance, maxDistance));
                continue;
            } else {
                // 找到可服务的网格外工程师，结束处理
                logger.info(String.format("getAutoNewGridOutMasterListTypeC-workId=%d-获取符合服务条件跨网格工程师%d:minDistance=%d,maxDistance=%d", masterList.size(), minDistance, maxDistance));
                // 网格外
                masterList.forEach((item) -> {
                    item.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_OUT);
                });
                if (logger.isDebugEnabled()) {
                    logger.debug("getAutoNewGridOutMasterListTypeC-workId:{}:返回跨网格工程师列表:{}", distributeMasterQuery.getWorkId(), masterList);
                }
                return masterList;
            }
        }
        return null;
    }

    /**
     * 查询网格外可派单工程师列表-人工派单
     */
    private List<ZsOrderDistributeVO> getNewGridOutMasterListTypeC(DistributeMasterQuery nonGridDistributeMasterQuery, List<Integer> excludeMasterIdList, int maxReworkCount, int maxReworkReminderCount) {

        logger.info("getNewGridOutMasterListTypeC-workId:{}", nonGridDistributeMasterQuery.getWorkId());

        if (CollectionUtils.isNotEmpty(excludeMasterIdList)) {
            nonGridDistributeMasterQuery.setExcludeMasterIdList(excludeMasterIdList);
        }

        List<ZsOrderDistributeVO> nonGridDistributeMasterList = this.listMandatoryDistributeMasterByQuery(nonGridDistributeMasterQuery);

        if (CollectionUtils.isNotEmpty(nonGridDistributeMasterList)) {
            this.getMasterListWorkInfo(nonGridDistributeMasterList, nonGridDistributeMasterQuery);
            nonGridDistributeMasterList = this.baseDistributeFilter(nonGridDistributeMasterList, nonGridDistributeMasterQuery, maxReworkCount, maxReworkReminderCount, null);

            if (CollectionUtils.isNotEmpty(nonGridDistributeMasterList)) {
                this.getMasterOnlineStatusAndScopeStatus(nonGridDistributeMasterList, nonGridDistributeMasterQuery);
                this.calcMasterOrderDistance(nonGridDistributeMasterQuery.getLongitude(), nonGridDistributeMasterQuery.getLatitude(), nonGridDistributeMasterList);
                nonGridDistributeMasterList.forEach(m -> m.setDistributeGrid(OrderDistributeConsts.DISTRIBUTE_GRID_OUT));
                return nonGridDistributeMasterList;
            }
        }
        return Collections.emptyList();
    }

    /**
     * 过滤待保护工程师
     *
     * @param masterList
     * @param distributeMasterQuery
     * @return
     */
    private List<ZsOrderDistributeVO> gridProtectDistributeFilter(List<ZsOrderDistributeVO> masterList, DistributeMasterQuery distributeMasterQuery) {
        if (CollectionUtil.isNullOrEmpty(masterList)) {
            return null;
        }
        return masterList.stream()
                .filter(vo -> Objects.equals(vo.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN))
                .filter(vo -> Objects.equals(vo.getMainSkillId(), distributeMasterQuery.getMainSkillId()))
                .collect(Collectors.toList());
    }
}
